下面的代码呢
MyClass a(new Foo(), new Bar());
如果“new Foo()”成功,但“new Bar()”抛出,Foo 会泄漏吗?
正在服用
std::unique_ptr<Foo>
或
std::shared_ptr<Foo>
作为参数,足以防止泄漏?
最佳答案
if "new Foo()" is successful, but "new Bar()" throws, does Foo will leak?
是的。
Is taking [...] as parameters, enough to prevent the leak?
不一定。这取决于你如何传递参数。例如,即使假设您的类构造函数看起来像这样:
MyClass::MyClass(std::unique_ptr<Foo> foo, std::unique_ptr<Bar> bar)
以下仍可能导致泄漏:
MyClass a(std::unique_ptr<Foo>(new Foo()), std::unique_ptr<Bar>(new Bar())
这是因为允许编译器按以下顺序计算上述表达式:
- 计算表达式
new Foo()
- 计算表达式
new Bar()
- 构建
std::unique_ptr<Foo>
临时从 1 的结果。 - 构建
std::unique_ptr<Bar>
临时从 2 的结果。
如果 2) 抛出异常,则您丢失了 Foo
.
但是,可以通过使用 std::make_unique<>()
来确保安全(仅限 C++14)或 std::make_shared<>()
,像这样:
MyClass a(std::make_unique<Foo>(), std::make_unique<Bar>());
现在不可能发生泄漏,因为std::make_unique<>()
(和 std::make_shared<>()
)立即将他们创建的对象与相应的智能指针相关联,而这两个操作(智能指针的动态分配和构造)不会与任何其他操作交错。
关于构造函数中的c++异常安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17355331/