Does std::vector < std::string > require manual memory release?

in practice, we encountered the use of vector < string > as a local variable to temporarily store a large number of string, and found that a large amount of memory was not released after running. After taking a look at the related problems, it is generally recommended to use swap to free memory. Will there really be a memory leak if you do not use swap? What is the best practice for storing large amounts of string using vector < string >?

Feb.28,2021

When

vector < string > is destructed, the memory requested by vector and string is properly freed without causing a memory leak. However, this memory will not necessarily be returned to the operating system. That is, this part of the memory is already available, but is still held by the process, see . Note: the effect of std::vector < std::string > (). Swap (x) on freeing memory is no different from that of direct destructing x, which depends on the destructing of vector to complete memory release. This scheme can safely empty x and free the memory it holds, and then x is still available.

if you observe that a large amount of memory is not freed before vector is destructed, it may be due to the extra memory held by vector (call vector::capacity to check how much memory vector holds). Vector's memory management mechanism causes this-- vector may not free memory after removing elements, and vector may request twice as much memory-- to reduce copy overhead when adding / removing elements.

when you need to release the extra memory held by vector, the standard practice is to call vector::shrink_to_fit . Considering that shrink_to_fit is implementation-related, you can also write one yourself:

std::vector<std::string> a(100, "abc");
a.erase(a.begin(), a.begin() + 10);
{ // shrink to fit
    std::vector<std::string> b;
    b.reserve(a.size());
    std::move(a.begin(), a.end(), std::back_inserter(b));
    a = std::move(b);
}
{ // another workaround
    a = std::vector<std::string>(std::make_move_iterator(a.begin()), std::make_move_iterator(a.end()));
}

vector does this to avoid frequently allocating memory and copying. Because the vector design is close to an array, it requires continuous storage of data. If you delete an element and release memory, adding it later may run out of continuous free space and need to be moved to another area of memory. Because the string data inside the string is in the heap, it is not directly placed in the vector, and the data is released when deleted from the vector. So you don't have to worry about the space that vector doesn't release, it's usually very small. Unless the amount of data in your vector varies greatly, you generally don't have to shrink the vector.


vector < int > does not need to free memory, but vector < string > requires swap to release
of course you will wonder that int does not need to free memory and string does not need to free memory (it is automatically destructed), but why is it different in vector? Built-in types such as
vector < int > do not need to free memory and are automatically freed. The essence of string type is pointer, and pointer types such as vector < string > , vector < int* > need to be released manually by swap.

Menu