将函数返回值分配给C++引用?

17

这是一个双重问题。 把函数的返回值赋给引用变量是否可行?例如:

Foo FuncBar()
{
    return Foo();
}

// some where else
Foo &myFoo = FuncBar();

这样做可以吗?我理解FuncBar()返回一个Foo对象,现在myFoo是对它的引用。

问题的第二部分。这是一种优化吗?如果你在循环中经常这样做,那么这样做会更好吗?

Foo &myFoo = FuncBar();
或者
Foo myFoo = FuncBar();

而且要考虑变量的使用情况,使用ref会不会导致更慢的解引用速度?

2个回答

23
Foo &myFoo = FuncBar();

无法编译。应该如下所示:

const Foo &myFoo = FuncBar();

因为 FuncBar() 返回一个临时对象(即 rvalue),只有 lvalues 可以绑定到非 const 引用。

这是安全的吗?

是的,这是安全的。

C++ 标准规定将临时对象绑定到 const 引用会延长临时对象的生命周期,使其与引用本身具有相同的生存期,从而避免了常见的悬空引用错误。


Foo myFoo = FuncBar();      

什么是复制初始化
它创建了由FuncBar()返回对象的副本,然后使用该副本初始化myFoo。在语句执行后,myFoo是一个单独的对象。

const Foo &myFoo = FuncBar();

FuncBar()返回的临时对象绑定到引用myFoo上,需要注意的是myFoo只是对返回的临时对象的别名,并不会创建一个新的对象。


3
按照标准来说,不应该这样做。但是通过编译器的扩展可能会实现。 - Alok Save
4
尽管有人可能将其定义为std::string*const&或其他垃圾,但我认为可以安全地假设在这里不考虑typedef。不要说了,我知道假设是邪恶的。但是,“根据标准不应编译”或类似的说法确实更好一些。 - Christian Rau
7
@Cheersandhth.-Alf:您的态度过于粗鲁了。如果您认为回答不正确,可以选择点踩。您的粗鲁行为并未得到赞赏,也不受欢迎。 - Alok Save
4
@Alf,你能否详细解释一下你的观点,因为我不是很理解你的意思。我能想到的唯一几种情况是,如果 Foo 实际上是一个 consttypedef 或者 Foo 包含一个 operator Foo&(),那么 Foo& myFoo = fooBar(); 才是合法的。这两种情况似乎都不是“普遍”的情况。如果我提供一个空的 class Foo 定义,则给定的代码在 g++ 中不能编译,并在 VC++ 中给出警告“使用了非标准扩展”。 - James Kanze
1
@Alf 是的。即使Foo& myFoo = fooBar();fooBar返回引用的情况下也是合理的;例如,使用类似于std :: map <> :: operator []的东西初始化引用并不罕见。 我只是在严格讨论fooBar返回对象的情况。 - James Kanze
显示剩余9条评论

2

你不是在“分配”给一个引用,而是在将其绑定到一个引用。

只有当类型为const且上下文是自动寿命期延长的情况下,这才是正确的。

一般来说,当Foo不是const类型时,你的示例应该无法编译。不幸的是,它们可能会在一个常见的编译器中编译,因为该编译器实现了语言扩展。最好使用至少两个编译器尝试示例(以及普通代码!)。


编辑:作为调查工作的例子,在发布问题之前,你应该使用至少两个编译器以最高警告级别编译以下内容(或非常相似),并且带有和不带有CONST定义。

struct Bar {};

#ifdef CONST
    typedef Bar const Foo;
#else
    typedef Bar Foo;
#endif

Foo FuncBar()
{
    return Foo();
}

int main()
{
    // som where else
    Foo &myFoo = FuncBar();
}

如果您还没有这样做,现在可以考虑一下。


2
你需要将警告级别提高到/W4。始终如此。 - Cheers and hth. - Alf
@Cheers:尝试了Alok答案的变体,但是没有成功。你知道其他方法吗?谢谢。 - Laurie Stearn
@Cheers:我在这里发布了一个临时答案。你觉得有意义吗? - Laurie Stearn
@LaurieStearn:是的,但请不要发布"temp answer"s。网络上有许多C++粘贴箱(请参阅C++标签信息中有关在线编译器的部分)。在提供的代码中,“prntArray”未定义。 - Cheers and hth. - Alf
@感谢支持:问题已解决!多亏了这个帖子里的信息,否则我可不知道该怎么办! :) - Laurie Stearn
显示剩余6条评论

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