Search code examples
c++11stlstdvectorstdstring

std::vector<std::string> insert empty string instead


In visual studio 2013, I created a std::vector and has store some strings in it. Then I want to make a copy of some string in the vector and append them to the end (suppose to move them to the end, after insert will do erase), but using insert method, I saw only empty strings at the end, very strange. I reproduced it with some simple test code,

std::vector<std::string> v;
std::string s = "0";
for (int i = 0; i < 7; ++i)
{
    s[0] = '0' + i; 
    v.push_back(s);
}
v.insert(v.end(), v.begin(), v.begin() + 3);
for (std::string& s : v) 
    std::cout << "\"" << s.c_str() << "\" ";

What I get there is "0" "1" "2" "3" "4" "5" "6" "" "" ""

I debugged into insert method, inside _Insert(..) method of vector class, it did some reallocating of memory, memory move/move and so on.

The first _Umove call move all 7 strings to new allocated memory, I think the std::move is invoked, the old memory has some empty string left.

Then the _Ucopy method try copy 3 items, but from old memory, as a result 3 empty string is attached. There is another _Umove call, I am not sure what's that for. After all thes, the old memory is freed and new memory attached to the vector.

Using a scalar type like int does not make wrong output, because the memory is copied, no std::move is invoked.

Am I doing something wrong here, or is it a MS Visual Studio's STL bug?


Solution

  • From this std::vector::insert reference:

    Causes reallocation if the new size() is greater than the old capacity(). If the new size() is greater than capacity(), all iterators and references are invalidated

    [Emphasis mine]

    You are adding elements to the vector while iterating the vector using iterators. Since this can cause the vector to be reallocated your iterators will be invalidated. That will lead to undefined behavior.