C++ vector::clear

2019-01-17 20:43发布

问题:

vector <weight> decoy;

void clear_decoy() {  

    decoy.clear();   

    vector<weight> (decoy).swap(decoy);  
}

In the above method clear_decoy(), what does vector<weight> (decoy).swap(decoy); mean please?

Does the method clear decoy or not? Thanks!

回答1:

It creates a new vector of Weight objects (which will be empty) and swaps it with decoy.

The reason for this is that by default, std::vector<t>::clear often doesn't actually reduce the storage used by a vector, it merely destroys all the objects contained there. This way, the vector has room to store more objects without reallocation in the future.

Sometimes, however, you want to trim the capacity in the vector. Swapping with a newly created vector (which lives until the end of it's line, and is therefore destroyed there) frees all the memory allocated by the vector.



回答2:

I've never seen that form before.

I have seen it written as:

vector<weight>().swap(decoy);

Which means "create a new empty vector, and swap it with the existing one.

vector<weight> (decoy).swap(decoy);

To understand that, break in to parts.

vector<weight>(decoy) create a new vector (with it's contents copied from the now empty decoy). The new vector is an anonomous temporary, so let's pretent it's name is newvector.

newVector.swap(decoy); swaps the new vector with decopy.

(Updated per comments to fix bug)



回答3:

That code is a failed attempt to use a common trick to ensure the memory allocated by the vector is freed. It may or may not actually do that, depending on whether or not the vector's copy constructor allocates memory to match the other vector's size, or its capacity.

To reliably free the memory, use the following:

void clear_decoy() {  
    vector<weight>().swap(decoy);  
}

This creates a temporary empty vector (with little or no memory allocated), swaps this with decoy so that the memory is now owned by the temporary, then destroys the temporary, freeing the memory.



回答4:

clear removes all entries from the vector, but may not necessarily deallocate the space. This swap idiom restores the vector to having no space allocated.



回答5:

As 0A0D mentions, the effect of swap is to exchange the underlying controlled memory between the two vectors. But this warrants a little more explanation.

When you clear a vector, the elements are removed from it at least as far as the programmer is concerned. size() becomes zero and capacity() may or may not change. But the Standard doesn't guarantee that the memory used by the vector will actually be returned back to the operating system. So if you had 1000 elements in the vector before the clear() and each took 1000 bytes memory, after the clear() each element's destructor is called, but the vector may still be holding on to a 1,000,000 byte allocation.

This is sometimes undesirable. The 'swap trick' you note above has the effect of exchanging the controlled memory between the two vectors. Hence decoy ends up with it's controlled memory reset.

Here is what is happening step-by-step:

  1. decoy elements are each erased. The elements' destructors are called, and the vector's size() becomes zero. The actual memory may not be deallocated.
  2. A new vector is constructed on the stack (vector<weight> (decoy)) and the elements from decoy are copied in to it. Since decoy was just clear()ed, no elements are copied in to the temporary vector. However, see edit below. You don't know that the controlled memory is not swapped.
  3. The temporary vector's and decoy's memory are swapped (.swap(decoy);) resulting in decoy being both cleared and it's memory transferred to the temporary.
  4. The temporary falls off the stack, resulting in it's memory being deallocated.

This is referred to as "the swap trick".

EDIT: As Mike mentions, the original programmer is doing it wrong. The temporary should not be constructed based on decoy, it should just be default constructed. You don't know for sure that swap() will only copy the elements and not the controlled memory underneath.



回答6:

With clear,

All the elements of the vector are dropped: their destructors are called, and then they are removed from the vector container, leaving the container with a size of 0.

Swap just swaps the two vectors,

Swap content

Exchanges the content of the vector by the content of vec, which is another vector of the same type. Sizes may differ.

After the call to this member function, the elements in this container are those which were in vec before the call, and the elements of vec are those which were in this. All iterators, references and pointers remain valid for the swapped vectors.

It seems you are swapping nothing really and just restores to default allocation. Clear can deallocate but it sometimes does not. You are not only reducing the size but lessening the space allocated with the swap statement.



标签: c++ vector