c++ - 如何使用静态转换管理共享对象的生命周期?

标签 c++ c++11 shared-ptr static-cast

我是 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/

相关文章:

使用 shared_ptr 到 const T 的 C++ 模板实例化

c++ - 尝试理解 libstdc++ 对 std::multiset 的实现

c++ - 全向阴影贴图

Cloud9 IDE 上的 C++11

c++ - boost shared_ptr 获取所有者计数

c++ - 如何混合 C++ 共享指针和对象引用

c++ - CWinApp CFrameWindow 未显示

c++ - 如何使用 cppzmq 从 ROUTER 套接字向特定的 DEALER 套接字发送 ZeroMQ 消息?

c++ - Lambda 捕获作为 const 引用?

c++ - 如何为 std::unordered_set 定义自定义键等价谓词?