31

写作是否const auto& [a, b] = f();保证延长从返回的对象的生命周期f(),或者至少是对象ab绑定的对象?通读该提案,我没有看到任何明显的语言来确保它确实有效,除非它只是被其他东西所涵盖。但是,以下内容不会延长临时的生命周期,所以我看不出它会如何被覆盖:

const auto& a = std::get<0>(f());

在论文的顶部,它似乎暗示它已被覆盖

分解声明的 cv-qualifiers 和 ref-qualifier 应用于为初始化程序引入的引用,而不是单个成员别名

但是在实际标准的建议措辞中,我看到的最接近的提及如下,尽管我不确定如何阅读它以获得我正在寻找的保证:

如果 e 是一个无括号的 id 表达式,命名从分解声明的标识符列表中引入的左值或引用,则 decltype(e) 是分解声明规范中给出的引用类型

似乎 gcc 和 clang 都将返回的对象的生命周期延长到基于wandbox 实验的范围结束。为我自己的类型实现所有花里胡哨的更丑陋的似乎延长了外部对象及其其他数据成员的生命周期。

尽管几乎可以肯定作者的意图,但我想确定该语言保证这是安全的。

4

1 回答 1

24

是的。诀窍是要意识到,尽管出现,结构化绑定声明的部分之前[并不适用于identifier-list中的名称。它们改为应用于声明隐式引入的变量。[dcl.struct.bind]/1

首先,引入一个具有唯一名称的变量e。如果 初始化程序中的赋值表达式具有数组类型并且不存在引用限定符,则具有类型并且每个元素都从赋值表达式的相应元素复制初始化或直接初始化,如初始化程序的形式所指定 。否则,定义为Aecv Ae

attribute-specifier-seq opt decl-specifier-seq ref-qualifier opt e initializer ;

其中声明永远不会被解释为函数声明,并且声明的除declarator-id之外的部分取自相应的结构化绑定声明。

然后将名称定义为元素的别名e或绑定到调用结果的get引用e

在您的示例中,就好像 by (假设f返回两个元素std::tuple):

const auto& e = f(); // 1
using E = remove_reference_t<decltype((e))>;
std::tuple_element<0, E>::type& a = get<0>(e);
std::tuple_element<1, E>::type& b = get<1>(e);

(除此之外,decltype(a)decltype(b)得到特殊处理以隐藏它们的参考性。)

很明显,第 1 行确实延长了f' 的返回值的生命周期。

于 2016-12-16T02:42:48.780 回答