Когда я запускаю код:
#include <iostream>
#include <vector>
using namespace std;
struct A_s {
int *arr;
unsigned int l;
A_s(unsigned int size) : l(size) {
arr = new int[size];
cout<<'\t'<<arr<<endl;
}
~A_s() {
delete[] arr; // works if line is removed
}
};
vector<A_s> vec;
int main() {
cout<<"vec 0"<<endl;
vec.emplace_back(1);
cout<<"vec 1"<<endl;
vec.emplace_back(1);
cout<<"vec 2"<<endl;
vec.emplace_back(1);
for(unsigned int i = 0; i < vec.size(); i++) cout<<&vec[i]<<endl;
cout<<"end"<<endl;
return 0;
}
Результат:
vec 0
0x761710
vec 1
0x761a90
vec 2
0x761ab0
mingw32-make: *** [Makefile:6: run] Error -1073740940
Программа работает без ошибок, если удалить строку delete[] arr. Вызывается ли деструктор до завершения программы? И даже если это так, почему это вызывает ошибку?
Подсказка: добавьте A_s(A_s &&) { cout << "Move!!" << endl; } и посмотрите, что получится.
emplace_back вполне может включать в себя копии. Если emplace_back должен увеличить вектор, записи существующий копируются, если тип не перемещается.
vec 0 0x1e1710 vec 1 0x1e1a90 Move!! vec 2 0x1e1ab0 Move!! Move!! mingw32-make: *** [Makefile:6: run] Error -1073740940 Итак, я думаю, он перемещает объекты ...
@RoyVaron Что касается вашего редактирования, это является дубликат. Вектор также перемещает элементы, когда растет, и здесь вступает в силу правило трех. Еще одно исправление - reserve, поэтому он никогда не растет, но вам лучше подчиняться правилу 3/5/0.
Я понимаю. Поскольку он перемещает объекты, я изменил вектор на vecotr<A_s *>. Я удалю РЕДАКТИРОВАТЬ. Всем спасибо за помощь!
@RoyVaron Независимо от того, используете ли вы сейчас вектор и emplace_back, вы должны хотя бы сделать так, чтобы ваши классы имели правильную семантику копирования.
vector<A_s *> - одна из худших вещей, которые вы можете сделать, потому что 1) вы теперь берете на себя нагрузку управления памятью, которую vector может делать за вас, и 2) вы можете случайно скопировать в другом месте и снова оказаться в этой дыре. Правильное решение - поддержка Правило пяти. В этом случае похоже, что вы не хотите когда-либо копировать, поэтому вы delete конструктор копирования и оператор присваивания, чтобы заблокировать любое копирование. ПримерЛибо сделайте A_s правильной семантикой копирования, либо delete - те функции, которые позволяют копировать, чтобы компилятор мог помечать любое использование копирования. Наличие неработающего класса, плавающего в вашем приложении, и надежда, что он не будет использоваться в ситуации копирования, - не способ решения проблемы.





vectorвыполняет множество операций по копированию и уничтожению копий, изменяя размер и перемещая записи. Это приводит к нарушению правила трех.