为什么类的析构函数被调用两次? shared_ptrs

时间:2017-06-02 09:33:03

标签: destructor shared-ptr

 class Class {
 public:
     Class()  {std::cout << "Constructor" << '\n';}
     ~Class() {std::cout << "Destructor" << '\n';}
 }; 

 int main() {
     std::cout<<"\nNew shared_ptr:\n";
     Class C;
     std::shared_ptr<Class> ptr(&C);
 }

跑完后我有:

New shared_ptr: 
Constructor 
Destructor 
Destructor

为什么?为什么析构函数被调用两次?

2 个答案:

答案 0 :(得分:0)

C ++中的原始指针存储对象的地址(指向对象),而C ++中的智能指针用作具有自动删除功能的原始指针的包装。

尽管智能指针通常不复制原始对象,但是在您的情况下,您将传递本地C的地址作为参数,因此C的副本将存储在堆中。

总结Class C;使用堆栈内存,而std::shared_ptr<Class> ptr(&C);使用堆内存。

main()函数的末尾,C超出范围,因此调用了析构函数。

然后共享指针会自动删除其在堆中的对象,因此将调用其对应的析构函数。

因此有两个析构函数。

答案 1 :(得分:0)

在不使用自定义删除器的情况下提供指向std::shared_ptr的原始指针意味着shared_ptr实现将delete的指针值在没有更多shared_ptr的情况下拥有指针。在您的示例中,这种情况发生在main被销毁的ptr的末尾,因此它尝试delete的指针等于&C。这仅对来自new表达式的指针有效。但是指针不是来自new;它只是main中定义的局部变量的地址。因此,这是未定义的行为。