【问题标题】:Object in smart pointer is not deleted after stack unwinding堆栈展开后不删除智能指针中的对象
【发布时间】:2019-12-20 04:38:42
【问题描述】:

我写了一个小程序,检查通过newmake_shared()函数创建shared_ptr的区别,以防出现异常。我通过make_shared() 到处读到它是异常安全的。

但这两种情况的有趣之处在于,两种情况下的析构函数都不会在堆栈展开后调用?我错过了什么吗?提前致谢。

#include <iostream>
#include <memory>

class Car
{
public:
    Car() { cout << "Car constructor!" << endl; throw std::runtime_error("Oops"); }
    ~Car() { cout << "Car destructor!" << endl; }
};

void doProcessing()
{
//    std::shared_ptr<Car> sp(new Car());
    std::shared_ptr<Car> sp2 = std::make_shared<Car>();
}

int main()
{
    try
    {
        doProcessing();
    }
    catch(...)
    {
    }
    return 0;
}

【问题讨论】:

  • 对象生命周期在构造函数成功完成时开始。如果构造函数抛出异常,则它没有被构造并且从未存在过,不是对象,不存在,并且不能被破坏。
  • @LightnessRacesinOrbit 哦,我期待链接后面有一些代码演示,但懒得打开它;)
  • @foreknownas_463035818 哈哈
  • 这里有一个有趣的哲学观点:如果你破坏了一个不存在的对象,它是继续不存在,还是不再存在> :)

标签: c++ exception shared-ptr smart-pointers


【解决方案1】:

什么对象?

这里智能指针中唯一的对象实际上并没有完成构造,因为它的构造函数抛出了。它不存在。

您不需要智能指针来证明这一点。只需从任何构造函数中抛出,您就会看到 the destructor body is not invoked

【讨论】:

  • 谢谢,我知道了。
【解决方案2】:

只是想添加一个答案,解决“我在任何地方都读到通过 make_shared() 它是异常安全的”部分问题,其余部分已经由轨道中的 Lightness Races 回答。

make_share 和 shared_ptr(new Car) 的区别可以通过下面的程序来演示。

class Car
{
public:
    Car() { cout << "Car constructor!" << endl; throw std::runtime_error("Car oops"); }
    ~Car() { cout << "Car destructor!" << endl; }
};

class Bycicle
{
public:
    Bycicle() { cout << "Bycicle constructor!, does not throw" << endl;}
    ~Bycicle() { cout << "Bycicle destructor!" << endl; }
};

void doProcessing(std::shared_ptr<Car> /*carPtr*/, std::shared_ptr<Bycicle> /*bPtr*/)
{

}

int main()
{
    try
    {
        doProcessing(std::shared_ptr<Car>(new Car), std::shared_ptr<Bycicle>(new Bycicle));
    }
    catch(std::exception& ex)
    {
        std::cout << "Ex is " << ex.what() << std::endl;
    }
    return 0;
}

在 C++17 之前,允许编译器进行以下函数调用(按所述顺序)

-- 与 Bycicle 的构造函数一起调用new Bycicle 调用shared_ptr 的ctor。

--调用抛出的Car的构造函数。

在这种情况下,正如所指出的,Car 从未完全构建,因此不会泄漏。然而,Bycicle 的构造函数已完全执行,它确实 泄漏(因为 shared_ptr NOT 还拥有该对象)。

调用doProcessing(std::make_shared&lt;Car&gt;(), std::make_shared&lt;Bycicle&gt;()); 保证完全分配对象的所有权传递给shared_ptr。

最后说明:这在 C++ 17 之后不适用,因为 C++ 17 保证参数被完全评估(仍然不能保证它们的评估顺序)。

【讨论】:

  • 非常感谢。现在我有了全貌。
猜你喜欢
  • 2013-08-19
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多