当获取unique_ptr的所有权的函数抛出异常时,对象破坏

时间:2014-11-13 17:13:06

标签: c++ c++11 unique-ptr

如果函数Foo()std::unique_ptr的所有权转移到函数Bar()并说Bar()抛出异常,则std::unique_ptr中包含的对象将被销毁。

在这种情况下,如何处理Foo()可能希望保留所有权的案例。

class A
{
public:
    std::unique_ptr<SomeData> getSomeData(...);
};

class B
{
public:
    pushToQ(std::unique_ptr<SomeData>);
    doSomething()
    ...
    popFromQ();
    ...
};

现在如果B::pushToQ()抛出QueueFullException,我将丢失getSomeData()生成的数据,这可能是我不想要的。

4 个答案:

答案 0 :(得分:6)

您要么转让所有权 - 要么您不是。如果你想转移,那么你不应该关心Bar是否可以抛出并杀死你的对象:

// i do not care what bar does with ptr, i am done with it
bar(std::move(ptr));

如果可能希望保留可能的所有权,那么转移自有服务是错误的解决方案。您想要通过引用传递unique_ptr,或者只是拉出原始指针,或者甚至只是使用shared_ptr。这取决于你的用例。但是没有中途所有权转移。

以下是一些例子。哪个更受欢迎完全取决于您:

bar(std::unique_ptr<Data>& ptr) {
    // not transferring, caller still owns the data
    something_that_might_throw();
    something_that_might_not();

    // ok got here?
    std::unique_ptr<Data> myPtr = std::move(ptr);
    // MINE NOW!!!
}

以上是&#34;唯一安全的解决方案,以异常安全的方式将unique_ptr移动到容器中,强有力地保证系统不会被破坏&#34; (来自MGetz

或者:

bar(Data* ptr) {
    // it really doesn't matter, caller always owns the data
    // just don't go doing something like this

    std::unique_ptr<Data> awful_idea(ptr);

    // now two separate people both think they own the data
    // and will both try to delete it. That'll work the first time...
}

或者是一个严格更好的版本,这样你就不会搞砸了,除非你真的很努力

bar(Data& data) {
    // well clearly the caller owns it
}

或者:

bar(std::shared_ptr<Data> ptr) {
    // we both share the data
    // it won't get deleted until both bar() and caller delete it
}

答案 1 :(得分:2)

然后不转让所有权。

SomeData&传递给Bar(),而不是。{/ p>

答案 2 :(得分:1)

如果pashTo()成功,您可以使用std::shared_ptr代替std::unique_ptr并释放您的实例,否则请保留您的副本。

答案 3 :(得分:1)

在被调用函数中,将unique_ptr存储在抛出的异常对象中。如果被调用者 - 或调用堆栈中的某个其他函数 - 想要保存它,则可以提取它。如果没有,它将被安全销毁。