将const unique_ptr引用作为参数传递

4
 void f1(unique_ptr<A[]>& upA){
    //some work...

    //callee can mess up smart pointer many ways for caller    
    upA.reset();

    //some work...
}

void f2(const unique_ptr<A[]>& upA){
    //some work...

    //compiler stops callee from ruining smart pointer many ways for caller    
    upA.reset();

    //some work...
}

f1(upAArray);
f2(upAArray);

在上面的代码中,调用f1是危险的,因为被调用方可以通过重置智能指针、释放智能指针等方式来破坏它。而调用f2则是安全的,一切都很顺利。如果被调用方试图做些不好的事情,编译器就会捕获到它。这样,在调用栈回溯并返回给调用者时,智能指针就是正确的。
重要提示:我不是在问如何最好地传递智能指针(我知道一个常规的原始指针void f3(A* pAArray){}就可以了)。我想知道的是,f2有什么问题?一般的建议是不要使用const ref作为唯一指针的参数,虽然我明白这不是最佳选择,但我不明白为什么它比f1更糟糕。
具体而言,针对f2有哪些理由呢?它有什么问题吗?它似乎安全可靠(尽管肯定不是最佳选择),我不明白为什么它会那么糟糕。

3
“一般建议”是不要通过引用来传递unique_ptr。它是const还是非const并不是问题所在。为什么f1f2需要使用unique_ptr - Nicol Bolas
3
智能指针用于表示所有权(谁负责该指针),如果您不需要这样做,那么可能需要使用其他类型。 - NathanOliver
这就是为什么它被称为“一般建议”,而不是“永远不要这样做”。 - Nicol Bolas
@NicolBolas 我想我误读了这条评论。也许“at all”这部分让我感觉比原意更绝对。 - François Andrieux
只有当你想要转移所有权时,才通过值或引用传递unique_ptr。同样,只有在想要共享所有权时,才通过值或引用传递shared_ptr。否则,请将其作为“Type const&”、“Type&”或“Type”(复制!)或“Type”或“Type const”的包含类型传递--使用原始指针不表示传递所有权的约定。 - Eljay
显示剩余8条评论
1个回答

7

将智能指针通过const引用(或裸引用)传递的一个缺点是,被调用方取决于调用方的实现细节。不需要与所有权交互的代码不应该依赖于智能指针,因为它们唯一的目的是对所有权进行建模。


你的意思是被调用者依赖于调用者的实现细节?能否举个简单的代码例子来说明一下?我不太确定你的意思。 - code
3
他的意思是,你知道调用者会使用 std::unique_ptr,所以你应该编写函数以接受它,从而将它们耦合在一起。如果函数只需要数组,则应该接收数组,并且不必关心如何存储/管理该数组。 - NathanOliver
如果你从 unique_ptr 改为 shared_ptr,那么你必须更改所有接受 unique_ptr 的函数,即使这些函数不使用 unique_ptr。如果一开始传递了一个原始指针,你就不需要担心这个问题。 - amc176

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接