我是 C++ 风格转换的新手,需要帮助来理解下面的代码是如何工作的(这是我为理解事物而编写的一些虚拟代码)。
#include <iostream>
#include <memory>
class A {
public:
A() : a(1) {
std::cout << "Creating A\n";
}
~A() {
std::cout << "Destroying A\n";
}
int a;
};
class B : public A {
public:
B() : b(2) {
std::cout << "Creating B\n";
}
~B() {
std::cout << "Destroying B\n";
}
int b;
};
int main() {
std::shared_ptr<B> objectB(new B());
{
std::shared_ptr<A> (static_cast<A*>(objectB.get()));
std::cout << "End of inner scope\n";
}
std::cout << "End of outer scope\n";
}
打印
Creating A
Creating B
Destroying A
End of inner scope
End of outer scope
Destroying B
Destroying A
我的理解:
Creating A -> B's ctor calls base class ctor
Creating B -> B's ctor
Destroying A -> ???
End of inner scope
End of outer scope
Destroying B -> B's dtor
Destroying A -> B's dtor calls base dtor
为什么我得到第一个 Destroying A
以及这里到底发生了什么?! A怎么会被销毁两次?
最佳答案
如果您确保输出已刷新(例如,通过使用 std::endl
),您会得到
Creating A
Creating B
Destroying A
End of inner scope
End of outer scope
Destroying B
Destroying A
两次删除 A
的原因是您正在从此处的原始指针构造 shared_ptr
:
std::shared_ptr<A> (static_cast<A*>(objectB.get()));
这个shared_ptr
完全独立于第一个,并且有自己的引用计数。因此,当作用域结束时,它会尝试删除它持有的 A
指针。如果您改为这样做:
std::shared_ptr<A>{objectB};
那你就不会遇到这个问题了。请注意,此处不需要 static_cast
。
注意 A
应该有一个 virtual
析构函数。 shared_ptr
有一个巧妙的析构机制,这意味着这在这个例子中并不重要,但一般来说,如果你要以多态方式删除对象,基类必须有一个虚拟析构函数。
关于c++ - 如何使用静态转换管理共享对象的生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17520381/