带有向量的类构造函数中的析构函数调用
Posted
技术标签:
【中文标题】带有向量的类构造函数中的析构函数调用【英文标题】:Destructor call in a class constructor with a vector 【发布时间】:2020-01-26 13:58:45 【问题描述】:我有以下类,它简单地包装了一个数组,并用构造函数向它添加了一些元素:
class myArray
public:
myArray();
myArray(int a, int b);
myArray(int a, int b, int c);
myArray(myArray&& emplace);
~myArray();
int& operator [](int id);
private:
int *data;
;
myArray::myArray()
data = new int[1];
data[0] = 0;
myArray::myArray(int a, int b)
data = new int[3];
data[0] = 0;
data[1] = a;
data[2] = b;
myArray::myArray(int a, int b, int c)
data = new int[4];
data[0] = 0;
data[1] = a;
data[2] = b;
data[3] = c;
myArray::~myArray()
std::cout << "Destructor"<<std::endl;
delete[] data;
int& myArray::operator [](int id)
return data[id];
myArray::myArray(myArray&& emplace) : data(std::move(emplace.data))
此外,我还有第二类,其中包含第一类元素的向量 (myArray
)。
class Queue
public:
Queue();
private:
std::vector<myArray> _queue;
;
Queue::Queue
_queue.reserve(1000);
for(int a = 0; a < 10; a++)
for(int b = 0; b < 10; b++)
for(int c = 0; c < 10; c++)
_queue.emplace_back(a,b,c);
我的问题是:为什么在 Queue 构造函数的末尾调用 myArray 元素的析构函数? Queue 对象在我的主程序中仍然存在,但 myArray 的析构函数释放了分配的内存,因此我得到了分段错误。
有没有办法避免调用析构函数,或者直到队列对象生命周期结束时才调用它?
【问题讨论】:
myArray 对象被复制到向量中,存在双重删除问题。结帐规则三 @billz Queue 构造函数中没有 myArray 的复制。不过,队列可能被复制到其他地方。 I cannot reproduce it 【参考方案1】:您的移动构造函数没有将移动对象上的 data
设置为 null,因此当移动对象被破坏时,它会尝试释放数据。
如果你有 c++14,你可以使用std::exchange
来实现这个:
myArray::myArray(myArray&& emplace)
: datastd::exchange(emplace.data, nullptr))
否则你需要这样做:
myArray::myArray(myArray&& emplace)
: dataemplace.data)
emplace.data = nullptr;
移动构造函数将由std::vector
调用,因为它会在您调用emplace_back
时重新分配以增加其容量。执行类似于以下步骤:
-
分配新内存来保存元素
使用在新内存中从前一个内存中的元素放置新元素来移动构造
销毁之前内存中的元素
释放之前的内存
【讨论】:
谢谢,修复了分段错误!如果我正确理解向量元素的内存被分配和释放两次?第一次在 Queue 构造函数的末尾,第二次在 Queue 解构函数的调用? 不,当您调用emplace_back
时,您的对象被构造,当您擦除元素或向量被破坏时,它被破坏。此外,当向量改变容量时,将使用所有现有元素的复制或移动构造函数创建新元素,然后销毁所有现有元素。以上是关于带有向量的类构造函数中的析构函数调用的主要内容,如果未能解决你的问题,请参考以下文章