结构化绑定中的 const 引用是否会延长分解对象的生命周期?
Do const references in structured bindings extend the lifetime of the decomposed object?
写 const auto& [a, b] = f();
是否保证延长从 f()
返回的对象的生命周期,或者至少 a
和 b
绑定的对象?通读 the proposal 我没有看到任何明显的语言来确保它确实如此,除非它只是被其他东西覆盖。但是,以下内容不会延长临时文件的生命周期,所以我看不出它是如何涵盖的:
const auto& a = std::get<0>(f());
论文的顶部似乎暗示它被覆盖了
the cv-qualifiers and ref-qualifier of the decomposition declaration are applied to the reference introduced for the initializer, not for the individual member aliases
但在实际标准的拟议措辞中,我看到的最接近的提及如下,但我不确定如何阅读它以获得我正在寻找的保证:
if e is an unparenthesized id-expression naming an lvalue or reference
introduced from the identifier-list of a decomposition declaration,
decltype(e) is the referenced type as given in the specification of
the decomposition declaration
gcc 和 clang 似乎都延长了返回对象的生命周期,直到范围结束基于 wandbox experiment. An uglier one 为我自己的类型实现所有的花里胡哨似乎延长了对象的生命周期外部对象及其其他数据成员。
虽然几乎可以肯定作者的意图,但我想确定该语言保证这是安全的。
是的。诀窍是要意识到尽管出现,[
之前的结构化绑定声明部分并不适用于 标识符列表 中的名称。它们适用于声明隐式引入的变量。 [dcl.struct.bind]/1:
First, a variable with a unique name e
is introduced. If the
assignment-expression in the initializer has array type A
and no ref-qualifier is present, e
has type cv A
and each element is copy-initialized or direct-initialized from the corresponding element
of the assignment-expression as specified by the form of the
initializer. Otherwise, e
is defined as-if by
attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt e
initializer ;
where the declaration is never interpreted as a function declaration
and the parts of the declaration other than the declarator-id are
taken from the corresponding structured binding declaration.
然后将名称定义为 e
元素的别名或绑定到在 e
上调用 get
结果的引用。
在您的示例中,就好像(假设 f
return 是一个双元素 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
的 return 值的生命周期。
写 const auto& [a, b] = f();
是否保证延长从 f()
返回的对象的生命周期,或者至少 a
和 b
绑定的对象?通读 the proposal 我没有看到任何明显的语言来确保它确实如此,除非它只是被其他东西覆盖。但是,以下内容不会延长临时文件的生命周期,所以我看不出它是如何涵盖的:
const auto& a = std::get<0>(f());
论文的顶部似乎暗示它被覆盖了
the cv-qualifiers and ref-qualifier of the decomposition declaration are applied to the reference introduced for the initializer, not for the individual member aliases
但在实际标准的拟议措辞中,我看到的最接近的提及如下,但我不确定如何阅读它以获得我正在寻找的保证:
if e is an unparenthesized id-expression naming an lvalue or reference introduced from the identifier-list of a decomposition declaration, decltype(e) is the referenced type as given in the specification of the decomposition declaration
gcc 和 clang 似乎都延长了返回对象的生命周期,直到范围结束基于 wandbox experiment. An uglier one 为我自己的类型实现所有的花里胡哨似乎延长了对象的生命周期外部对象及其其他数据成员。
虽然几乎可以肯定作者的意图,但我想确定该语言保证这是安全的。
是的。诀窍是要意识到尽管出现,[
之前的结构化绑定声明部分并不适用于 标识符列表 中的名称。它们适用于声明隐式引入的变量。 [dcl.struct.bind]/1:
First, a variable with a unique name
e
is introduced. If the assignment-expression in the initializer has array typeA
and no ref-qualifier is present,e
has typecv A
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer. Otherwise,e
is defined as-if byattribute-specifier-seqopt decl-specifier-seq ref-qualifieropt
e
initializer ;where the declaration is never interpreted as a function declaration and the parts of the declaration other than the declarator-id are taken from the corresponding structured binding declaration.
然后将名称定义为 e
元素的别名或绑定到在 e
上调用 get
结果的引用。
在您的示例中,就好像(假设 f
return 是一个双元素 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
的 return 值的生命周期。