我的代码如下:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct A {
A() { cout << "c"; }
~A() { cout << "d"; }
};
int main() {
shared_ptr<void> a = make_shared<vector<A>>(3);
auto b = static_pointer_cast<vector<A>>(a);
b->push_back(A{});
return 0;
}
它打印:
ccccdddddddd
表示析构函数称为两次。为什么会发生这种情况以及如何解决?
答案 0 :(得分:2)
没有什么要修复的。每个对象不会两次调用析构函数。而是,您没有跟踪所有构造函数。将跟踪添加到副本并移动构造函数,如
struct A {
A() { cout << "c"; }
A(const A &) { cout << "C"; }
A(A &&) { cout << "M"; }
~A() { cout << "d"; }
};
进行此更改后,您的输出应为
ccccMCCCdddddddd
表示8个构造函数调用和8个析构函数调用。
答案 1 :(得分:1)
析构函数调用是b->push_back(A{});
而不是static_pointer_cast
的结果
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct A {
A() { cout << "c"; }
~A() { cout << "d"; }
};
int main() {
shared_ptr<void> a = make_shared<vector<A>>(3);
auto b = static_pointer_cast<vector<A>>(a);
return 0;
}
显示cccddd
。
之所以进行额外的析构函数调用,是因为矢量可能需要增加其在push_back
上的容量,并且完成此操作后,它可能需要将现有元素移动/复制到新位置,并且删除旧元素。因此,您看到的其他析构函数就是这个结果。
在您的情况下,默认情况下已创建复制/移动构造。如果您手动定义它们并向其中添加日志,则可以看到它们匹配。
struct A {
A() { cout << "c"; }
A(const A&) { cout << "C"; };
A(A&&) { cout << "M"; };
~A() { cout << "d"; }
};
防止这种情况的唯一方法是创建向量,使其具有足够大的容量以容纳要保存在其中的所有元素。