【问题标题】:Why assign a return value to a reference?为什么要为引用分配返回值?
【发布时间】:2011-01-13 20:02:47
【问题描述】:

我正在查看一些代码,所有对返回字符串的函数的调用都分配给了一个引用。函数原型类似于:

 std::string GetPath(const std::string& top);

它被用作

std::string& f = GetPath(cw);

 const std::string& f = GetPath(cw);

为什么要在这里使用参考而不是

 std::string f = GetPath(cw);

【问题讨论】:

标签: c++


【解决方案1】:

如果函数返回一个引用(它没有),那么您可能需要将返回值分配给一个引用以保持“最新" 对该对象进行任何更改。返回的引用必须是一个生命周期超过函数末尾的对象。

或者(如果返回的引用不是-const),因为您想保留对该对象的引用以将其作为后续点进行变异。 (如果您想立即对其进行变异,您可以直接进行,无需存储引用。)

当函数返回一个值时,您可以将其分配给const 引用(非const 引用将是非法的)并将对象的生命周期延长到引用的生命周期。但是,效果与将值直接存储在对象中完全相同(除了const)。

任何认为它可能效率较低的想法都可能被证明是没有根据的,如果你愿意,你也可以使用const 来限定对象。 (大多数编译器会消除隐含的临时值,并在正在初始化的对象中构造返回值。)

由于对象类型是按值从函数返回的,因此它必须是可复制的,因此没有理由使用引用,因为担心它不是。

【讨论】:

  • 哇,你甚至不必添加毫无根据的侮辱!
  • 我可能把我当成一个老人(谁知道?),但上次我查看时,将临时对象绑定到 const 引用是一个很好的、廉价的优化技巧,只是被嫉妒地分享了。我可以看到移动语义会使它变得毫无用处,但是 C++03 发生了什么让这种“误导”?
  • 如果代码的作者是已知的,以上内容将是相当侮辱性的。它将代码的作者描述为“被误导”和“恐惧”。并且相信关于作者的观点,对 OP 没有帮助。相比之下,说代码的作者不称职或愚蠢,只是一种简单的评估。它通过知道不相信其他任何代码都有充分的理由来帮助 OP。
  • @Alf:“误导”不是侮辱。它只是意味着“错误地行事”。我们都会犯错,这不是什么新鲜事。相反,“愚蠢”和“无能”受到不同的对待,因为它们被用来贬低和挫败一个人,更不用说他们的行为是错误的。 “恐惧”也不是侮辱。它只是意味着“警惕”、“关心”或“小心”;难道我们不小心吗?不,答案之间的区别在于随意和非恶意阅读此答案不会产生侮辱,而您的答案则将它们放在首位。
  • @Alf:另外,sbi 已经证明他认为这种代码是值得的。你为什么不直接说他愚蠢或无能?你只对无法回应的人这样做吗?非常成熟。
【解决方案2】:

这可能是针对被调用的函数返回引用的情况的过度优化,如下所示:

const std::string& func();
...
const std::string& tmp = func();
...

保存字符串副本。

【讨论】:

  • 如果您注意到做这样的事情是多么没有意义,这个答案会更好,但是是的,您可能已经确定了动机。
  • 嗯,我不认为这完全没有意义。我认为在某些极端情况下,您可能希望在 C++98 中执行此操作。
【解决方案3】:

好吧,这完全没有意义。而且看起来很糟糕。并且不是有效的 C++。只是不要这样做。

编辑:以便更好地理解我的意思

reference & var = funcNotReturningReference(); //invalid C++
const reference & cvar = funcNotReturningReference(); //silly C++, no saving costs (reference to temporary stops temporary from being released, but this code does not help anything)

【讨论】:

  • 我打赌你会为此获得+20。荣誉。
  • -1。 const std::string& result = function(); 是完全有效的 C++。
  • 推理总比侮辱好。
  • @peenut:我同意。不幸的是,你的推理是有缺陷的。 :)
  • @peenut 它仍然存在缺陷。 struct Foo { std::string str; Foo() : str("Long string here") {} }; Foo f; Foo& bar() { return f; } /* ... */ const Foo& ref = bar(); 可能非常好为您节省成本。如果您使用一个非常复杂的对象而不是std::string,那么节省的成本可能非常显着。我并不是说他们永远都是,只是他们可能会。围绕这个问题浮现的所有这些“这总是毫无意义和愚蠢的”是毫无根据的,并且以一种可悲的方式概括实际上是一个相当复杂的主题。
猜你喜欢
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 2018-06-12
  • 1970-01-01
  • 2012-02-22
相关资源
最近更新 更多