gpt4 book ai didi

c++ - range-for 表达式中的临时生命周期

转载 作者:IT老高 更新时间:2023-10-28 22:04:37 25 4
gpt4 key购买 nike

考虑一个可以用作范围的简单类A:

struct A { 
~A() { std::cout << "~A "; }

const char* begin() const {
std::cout << "A::begin ";
return s.data();
}

const char* end() const {
std::cout << "A::end ";
return s.data() + s.size();
}

std::string s;
};

如果我在 range-for 中创建一个临时 A,它的工作原理与我希望的完全一样:

for (auto c : A{"works"}) {
std::cout << c << ' ';
}

// output
A::begin A::end w o r k s ~A

但是,如果我尝试包装临时:

struct wrap {
wrap(A&& a) : a(std::move(a))
{ }

const char* begin() const { return a.begin(); }
const char* end() const { return a.end(); }

A&& a;
};

for (auto c : wrap(A{"fails"})) {
std::cout << c << ' ';
}

// The temporary A gets destroyed before the loop even begins:
~A A::begin A::end
^^

为什么 A 的生命周期没有针对整个范围-for 表达式进行延长,我怎样才能在不复制 A 的情况下实现这一点?

最佳答案

临时的生命周期没有延长的原因是标准如何定义基于范围的for循环

6.5.4 The range-based for statement [stmt.ranged]

1 For a range-based for statement of the form

for (for-range-declaration:expression)statement

let range-init be equivalent to the expression surrounded by parentheses

( expression )

and for a range-based for statement of the form

for (for-range-declaration:braced-init-list)statement

let range-init be equivalent to the braced-init-list. In each case, a range-based for statement is equivalent to

{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}

请注意,auto && __range = range-init; 会延长从 range-init 返回的临时对象的生命周期,但不会延长嵌套临时对象的生命周期范围初始化内部

恕我直言,这是一个非常不幸的定义,甚至被讨论为 Defect Report 900 .它似乎是标准中唯一隐含绑定(bind)以延长表达式结果的生命周期而不延长嵌套临时对象的生命周期的部分。

解决方案是在包装器中存储一个拷贝 - 这通常会破坏包装器的目的。

关于c++ - range-for 表达式中的临时生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29990045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com