什么时候不使用`auto &&`?

bal*_*lki 18 c++ auto c++11 universal-reference

  auto&& mytup = std::make_tuple(9,1,"hello");
  std::get<0>(mytup) = 42;
  cout << std::get<0>(mytup) << endl;
Run Code Online (Sandbox Code Playgroud)
  1. 从make_tuple返回时是否涉及复制/移动(没有RVO)?
  2. 是否导致未定义的行为?
  3. 我都可以读写通用引用.可以auto&& var = func()总是使用而不是auto var = func()没有复制/移动?

Luc*_*ton 14

在初始化程序是返回短寿命右值引用的函数调用的情况下,它只会出现问题.用更少的单词和更多的代码:

// Fine; lifetime extension applies!
auto&& ref = 42;

auto id = [](int&& i) -> int&& { return std::move(i); };
auto&& uhoh = id(42);
// uhoh is now a stale reference; can't touch it!
Run Code Online (Sandbox Code Playgroud)

相比之下,auto uhoh = id(42);本来可以.

在您的情况下,因为std::make_tuple返回值而不是右值引用,所以没有问题.

我认为真正的危险来自具有右值参考参数的那些函数和函数模板,并且返回对某些子对象的rvalue引用,其寿命依赖于那些子对象.(话虽这么说,就像auto&& ref = std::move(42);展示问题一样简单!)

考虑到C++ 11,情况并非全新T const& ref = bar(T_factory());.

  • +1,我记得在'T const&pass(T const&t){返回t; }例子当试图改进Clang对返回临时引用的检测时......不幸的是它需要程序间分析来检测*可能的*问题:x (4认同)

Joe*_*rgB 8

  1. 是.从不返回引用类型的函数返回的任何内容都可能涉及复制/移动.这就是RVO的意义所在.您的引用绑定的对象需要以某种方式初始化.

  2. 不,为什么要这样?绑定到引用的临时/ prvalue的生命周期由引用的范围确定.

  3. 如果func()没有返回引用类型,那么效率(行为)应该没有任何差别

之间

auto&& var = func();
Run Code Online (Sandbox Code Playgroud)

auto var = func();
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,构造具有生命周期到包含块的末尾的对象.在一种情况下,它有自己的名称,在另一种情况下,它通过引用命名.在这两种情况下,名称都可以用作左值.在任何一种情况下,RVO都可以同样适用.

有些编译器可能更好地优化本地对象而不是参考,即使在当前情况下,引用临时与本地对象实际上没有区别.

如果func()可能返回引用,则情况会有很大不同 - 在这种情况下,您必须决定是否要复制/移动.