2
TestDelete::TestDelete(int i) {
    this->i = i;
    std::cout <<"TestDelete constructor for "<<this->i<<"\n";
}

TestDelete::~TestDelete() {
    std::cout <<"TestDelete destructor for "<<this->i<<"\n";
}

int main () {
  std::vector<TestDelete> pt;
  pt.push_back(TestDelete(1));
  pt.push_back(TestDelete(2));

  return 0;
}

上面的代码片段输出如下

1 的 TestDelete 构造函数

1 的 TestDelete 析构函数

2 的 TestDelete 构造函数

1 的 TestDelete 析构函数

2 的 TestDelete 析构函数;

1 的 TestDelete 析构函数;

2 的 TestDelete 析构函数;

我理解的实现push_back基于复制交换概念,因此调用了临时对象的构造函数和析构函数。但是,如果您注意到对析构函数的额外调用object1

有人可以解释这里发生了什么吗?

4

3 回答 3

2

让我们看看您的实现可能在做什么:

std::vector<TestDelete> pt;

创建一个大小为 0 的向量。

pt.push_back(TestDelete(1));

重新分配大小为 1 的向量。通过复制构造(移动构造)临时添加新元素。

pt.push_back(TestDelete(2));

重新分配大小为 2 的向量。这意味着复制构造(或移动构造)先前创建的元素,并删除原始元素。通过复制构造(移动构造)临时添加新元素。

这是一个活生生的例子,也有一个改进,它可以防止向量重新分配。请注意,临时对象仍在被破坏,这让我感到惊讶;我猜编译器可以省略副本。

于 2013-05-23T09:07:42.587 回答
2

您正在打破3 规则,并且您的一个对象被复制,并且您看到了该副本的析构函数。

如果您添加一个复制构造函数和一个带有日志记录的复制赋值运算符,您将看到可以理解的行为。

编辑:由于人们对评论中的这个答案感到困惑 - 这只是为了表明没有任何问题,只是如果您添加 CC/CAO 和日志记录,您会看到所有对象都被正确创建/分配/销毁. 程序正确性不需要 CC/CAO。关于为什么 std::vector 可能按照您在下面看到的顺序创建/分配/销毁的原因,下面有一个更好的答案。对造成的任何混乱表示歉意。

于 2013-05-23T08:37:37.860 回答
0

这是因为std::vector的调整大小政策。然后它被填满,它以某种因素增长。这需要新的内存分配+旧的内存释放(因此需要析构函数的调用)。

例如,如果您事先保留内存,则不会发生调整大小:

$ 猫 main.cpp

#include <iostream>
#include <vector>

class TestDelete {
public:
        TestDelete(int);
        ~TestDelete();

        int i;
};

TestDelete::TestDelete(int i) {
    this->i = i;
    std::cout <<"TestDelete constructor for "<<this->i<<"\n";
}

TestDelete::~TestDelete() {
    std::cout <<"TestDelete destructor for "<<this->i<<"\n";
}

int main () {
  std::vector<TestDelete> pt;

  pt.reserve(10); // reserve memory for 10 objects
  pt.push_back(TestDelete(1)); // so no resize would be needed
  pt.push_back(TestDelete(2));

  return 0;
}

$ ./a.out

TestDelete constructor for 1 // temporary object constructed
TestDelete destructor for 1  // temporary object destructed
TestDelete constructor for 2  // temporary object constructed
TestDelete destructor for 2  // temporary object destructed
TestDelete destructor for 1  // vector destructed
TestDelete destructor for 2 // vector destructed
于 2013-05-23T08:58:36.880 回答