2016-11-21 5 views
0

В visual studio 2013 я создал std :: vector и сохранил некоторые строки в нем. Затем я хочу сделать копию некоторой строки в векторе и добавить ее в конец (предположим, чтобы переместить их до конца, после того, как вставка будет удалять), но используя метод insert, я видел только пустые строки в конце, очень странный. Я воспроизводил его с каким-нибудь простым тестовым кодом,std :: vector <std::string> Вставить пустую строку вместо

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() << "\" "; 

Что я получаю там "0" "1" "2" "3" "4" "5" "6" "" "" ""

Я отлаживал метод вставки, внутри _Insert (..) метода векторного класса, он делал некоторое перераспределение памяти, перемещение/перемещение памяти и т. Д.

Первый _Umove вызов переместить все 7 строк в новую выделенную память, я думаю, что std :: move вызывается, у старой памяти осталось несколько пустых строк.

Затем метод _Ucopy попытается скопировать 3 элемента, но из старой памяти, в результате будет добавлена ​​3 пустая строка. Существует еще один звонок, я не уверен, для чего это нужно. После того, как все это, старая память освобождается и новая память привязана к вектору.

Использование такого скалярного типа, как int, не делает неправильный вывод, так как память скопирована, вызов std :: move не вызывается.

Я делаю что-то неправильно здесь, или это ошибка STL MS Visual Studio?

ответ

1

От this std::vector::insert reference:

Причины перераспределению, если новый size() больше, чем старый capacity(). Если новый size() больше capacity(), все итераторы и ссылки аннулируются

[курсив мой]

Вы добавляете элементы в вектор, а итерация вектор с использованием итераторов. Поскольку это может привести к перераспределению вектора, ваши итераторы будут признаны недействительными. Это приведет к не определено поведение.

+0

Как я понимаю, перераспределение вызывает итераторы и ссылки недействительными, что должно произойти после возврата вставки. Любой итератор и ссылка на вектор являются недействительными, но это происходит во время вызова, это странно для меня. Я пытаюсь зарезервировать некоторое пространство перед вставкой, тогда оно работает. Это только обходной путь. Я попробую с другим компилятором позже. –

+0

@TigerHwang Вы передаете два итератора функции 'insert'. Как только функция 'insert' создает пространство для новых элементов, те итераторы, которые вы передаете, становятся недействительными. Использование другого компилятора не решит вашу проблему. Резервирование пространства является единственным решением. –

+0

Мой объект должен переместить некоторые строки в векторе в конец, поэтому я попробовал другой метод std :: move (v.begin(), v.begin() + 3, v.end()). Это приводит к сбою утверждения из-за итератора + смещение вне диапазона. С std :: move (v.begin(), v.begin() + 3, v.end() - 3), это не подводит, но результат не то, что я хочу. Любое предложение? –

Смежные вопросы