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

Ras*_*ida 0 c++ unique-ptr c++11

如果函数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();
    ...
};
Run Code Online (Sandbox Code Playgroud)

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

Bar*_*rry 6

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

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

如果你可能想保留所有权也许,然后将其转移ownserhip是错误的解决方案.你想要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!!!
}
Run Code Online (Sandbox Code Playgroud)

以上是"唯一安全的解决方案,以异常安全的方式将unique_ptr移动到容器中,同时强有力地保证系统不会被破坏"(来自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...
}
Run Code Online (Sandbox Code Playgroud)

或者是一个严格更好的版本,所以你不能搞砸它,除非你真的很努力

bar(Data& data) {
    // well clearly the caller owns it
}
Run Code Online (Sandbox Code Playgroud)

要么:

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