堆栈展开后智能指针中的对象不会被删除
Object in smart pointer is not deleted after stack unwinding
我写了一个小程序,检查通过 new
和 make_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;
}
什么对象?
这里唯一一个智能指针中的对象并没有真正完成构造,因为它的构造函数抛出了。它不存在。
您不需要智能指针来演示这一点。只需从任何构造函数中抛出,您就会看到 the destructor body is not invoked.
只想添加一个解决 "I read everywhere that via make_shared() it is an exception-safe" 部分问题的答案,其余部分已由 Lightness Races in Orbit 回答。
make_share 和 shared_ptr(新车)之间的区别可以通过下面的程序演示。
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 之前,允许编译器进行以下函数调用(按照描述的顺序)
-- 调用 new Bycicle
和 Bycicle 的构造函数,但 NOT 调用 shared_ptr
.
的构造函数
-- 调用抛出的Car的构造函数
在这种情况下,正如指出的那样,Car 从未完全构造好,因此不会泄漏。但是 Bycicle 的构造函数已完全执行并且它 确实 泄漏(因为 shared_ptr 确实 NOT 还拥有该对象)。
调用 doProcessing(std::make_shared<Car>(), std::make_shared<Bycicle>());
保证 完全 分配对象的所有权传递给 shared_ptr。
最后说明:这在 C++ 17 之后不适用,因为 C++ 17 保证参数被完全计算(仍然不能保证它们被计算的顺序)。
我写了一个小程序,检查通过 new
和 make_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;
}
什么对象?
这里唯一一个智能指针中的对象并没有真正完成构造,因为它的构造函数抛出了。它不存在。
您不需要智能指针来演示这一点。只需从任何构造函数中抛出,您就会看到 the destructor body is not invoked.
只想添加一个解决 "I read everywhere that via make_shared() it is an exception-safe" 部分问题的答案,其余部分已由 Lightness Races in Orbit 回答。
make_share 和 shared_ptr(新车)之间的区别可以通过下面的程序演示。
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 之前,允许编译器进行以下函数调用(按照描述的顺序)
-- 调用 new Bycicle
和 Bycicle 的构造函数,但 NOT 调用 shared_ptr
.
-- 调用抛出的Car的构造函数
在这种情况下,正如指出的那样,Car 从未完全构造好,因此不会泄漏。但是 Bycicle 的构造函数已完全执行并且它 确实 泄漏(因为 shared_ptr 确实 NOT 还拥有该对象)。
调用 doProcessing(std::make_shared<Car>(), std::make_shared<Bycicle>());
保证 完全 分配对象的所有权传递给 shared_ptr。
最后说明:这在 C++ 17 之后不适用,因为 C++ 17 保证参数被完全计算(仍然不能保证它们被计算的顺序)。