2013-10-17 81 views
0

我们使用C++ 98(较旧的一个)。返回对智能指针的const引用vs使用引用作为参数

比方说,我们有一张桌子,并考虑查找。 Ptr是一些智能指针。 下面的语句1. - .3正确或两种情况都考虑从呼叫者的角度来看是同样安全/不安全 ?查找的

函数原型:

const Y::Ptr & lookup(const X::Ptr & x); 

和呼叫者函数,其中查找叫做:

const Y::Ptr & ret = lookup(x); 

其中,x是X :: PTR对象或X :: PTR的参考。所以,我们有以下两行的用法。

  1. 函数参数const X::Ptr &。这通常是安全的,并避免函数调用时复制构造函数X::Ptr。调用者负责为对象X保留X的引用,以在查找函数调用的持续时间内持续。
  2. 返回值const Y::Ptr &。这是不安全的,因为在此引用位于堆栈中的短暂持续时间内,如果线程被中断/挂起并且另一个线程从表中删除条目,则Y对象和Y::Ptr对象都将被删除。结果,堆栈上的Y::Ptr引用引用了一个不存在的Ptr对象。
  3. 本地参考const Y::Ptr &来存储查找的返回值。这是不安全的,因为#2类似的原因,但可能更糟,因为调用方函数中的本地引用的作用域比堆栈上的ref长作为返回值。

回答

0

我想你已经明白了。显然,解决方案是按值返回智能指针。请注意,您的#2点完全被#3包含,所以没有太多需要特别考虑点#2(因为没有关于您没有或者不能使用的参考点)。

0

很大程度上取决于lookup的作用,以及您正在尝试以什么方式实现 。你逻辑上返回一个值,还是参考某些内部数据?在很多功能名称为 (如lookup)的情况下,它是后者,并且返回值作为参考通常很重要。 (一个明显的例子是 函数,如operator[],在std::vector。)但是,除非 语义需要参考,但是,您最好根据值返回 。

类似的,在呼叫站点。如果调用者需要参考 您的数据结构,他应该声明变量为 作为参考;否则,他应该宣布它是一个价值。 ( 当然,如果函数返回一个值,那么从来没有任何 合理的情况,其中局部变量应该是一个参考。)

我觉得多线程是一个红鲱鱼在这里。如果其他线程 正在修改数据结构lookup的使用,则需要 外部同步,句点。如果函数返回 作为参考,并将其保留为参考,则关键 部分包含参考的有效期,但这通常不是一个大问题;如果是,则调用者可以将 结果存储为一个值,并用它来完成。

作为一般规则,C++更喜欢值语义。语言是 优化考虑到这一点,包括特殊规则允许编译器 优化不必要的副本。不要打 吧。关于唯一的例外情况是使用 const作为函数参数的参考。 (但是即使在这里,你想要的是 一致,无处不在的约定是通过 引用const类型的引用,其他类型的值如果这是在你的代码中使用的规则 ,那么系统地使用它,而不是 异常)

+0

这个问题不仅仅是参考vs值,而是在初始文章中描述的两个问题中哪一个更为安全。 – user2890398