首页 > 解决方案 > 带有向量的类构造函数中的析构函数调用

问题描述

我有以下类,它简单地包装一个数组并使用构造函数向其中添加一些元素:

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 的析构函数释放了分配的内存,因此我得到了分段错误。

有没有办法避免调用析构函数,或者直到队列对象生命周期结束时才调用它?

标签: c++vectorconstructor

解决方案


您的移动构造函数不会data在移动的对象上设置为 null,因此当移动的对象被破坏时,它将尝试释放数据。

如果你有 c++14,你可以std::exchange用来实现这个:

myArray::myArray(myArray&& emplace)
 : data{std::exchange(emplace.data, nullptr)})
{}

否则你需要这样做:

myArray::myArray(myArray&& emplace)
 : data{emplace.data)
{
  emplace.data = nullptr;
}

移动构造函数将被调用,std::vector因为它会在您调用时重新分配以增加其容量emplace_back。执行以下步骤:

  1. 分配新内存来保存元素
  2. 使用从前一个内存中的元素放置新内存中的新元素来移动构造
  3. 销毁前一个内存中的元素
  4. 释放之前的内存

推荐阅读