0

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?

0

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

As I understand, reallocation cause iterators and reference invalidated, that should happen after insert is returned. Any iterator and reference to the vector is invalidated, but this happen during the call, it's strange to me. I try reserve some space before insert, then it works. It's only a workaround. I will try with other compiler later.
@TigerHwang You are passing two iterators to the insert function. As soon as the insert function makes space for the new elements, those iterators you pass become invalid. Using another compiler will not solve your problem. Reserving space is the only solution.
My object is to move some strings in the vector to the end, so I tried another method std::move(v.begin(), v.begin() + 3, v.end()). This cause assertion failure due to iterator + offset out of range. With std::move(v.begin(), v.begin() + 3, v.end() - 3), it does not fail, but the result is not what I want. Any suggestion?
@TigerHwang In that case I suggest using a normal for loop that iterates three times. In the loop get the value of the first element, remove the first element, and add the value at the back.
Thanks, I just remember a rotate method in std should do the trick.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.