【问题标题】:Structured bindings and mandatory copy elision结构化绑定和强制复制省略
【发布时间】:2017-01-21 21:36:55
【问题描述】:

如果你像这样使用结构化绑定

auto [a, b, c] = std::make_tuple(1, 10.0, "string object"s);

那么返回的元组中的副本是否会被删除,对象会直接进入abc,或者初始化是来自单个元组元素的移动构造吗?我怀疑这会导致复制发生,但我不确定标准中对强制复制省略的描述是否能处理这种情况。

【问题讨论】:

  • "返回的元组中的副本是否会被删除,对象会直接进入 a、b 和 c" 否。"是否初始化是来自单个元组元素的移动构造" 否。
  • @cpplearner 那么他们被复制了吗?

标签: c++ c++17 copy-elision structured-bindings


【解决方案1】:

正如this excellent answer 所涵盖的,声明相当于:

auto e = std::make_tuple(1, 10.0, "string object"s);
int& a = get<0>(e);
double& b = get<1>(e);
std::string& c = get<2>(e);

除了没有名字e。在此上下文中,get 函数会产生对所选项目的左值引用。

在 C++17 中,auto name = prvalue;is defined 声明一个名为 name 的对象,其类型为 decltype(prvalue),使用纯右值表达式初始化——没有像以前版本中那样可以省略的中间临时对象。

换句话说,e 声明的行为与:

std::tuple<int, double, std::string> e {1, 10.0, "string object"s};

然后a,b,c 是对该元组元素的引用。


注意:以上解释对应最新的C++17草稿源码;当然,在 C++17 最终确定之前,行为可能会发生变化。

【讨论】:

  • 在这个例子中,a,b,c&amp;&amp;s 和 get 被称为 std::move(e) 的等价物。
  • @T.C. e 是一个左值,所以get&lt;N&gt;(e) 应该是接受左值引用并返回左值引用的版本? (但即使你是对的,最终结果也是一样的,因为 a,b,c 也是左值)。 [dcl.decomp/3] 目前说“否则,初始化程序是get&lt;i&gt;(e)
  • 这里的措辞相当棘手。关键句是“在任何一种情况下,如果实体 e 的类型是左值引用,则 e 是左值,否则是 xvalue。”
  • @T.C.好的,所以 [dcl.decomp]/3 中的 e 与 /1 中的 e 不同,后者被指定为auto e = prvalue; 的行为(在所有情况下都是左值)
  • 对,它不完全是 /1 中引入的 e-the-variable。本质上这是核心语言风格的完美转发。
猜你喜欢
  • 2018-01-23
  • 1970-01-01
  • 1970-01-01
  • 2014-04-22
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
相关资源
最近更新 更多