Cra*_*lds 7 c++ shared-ptr c++11 ranged-loops
我编写了一个c ++函数,它汇总了一些数据,然后返回一个包含数据std::shared_ptr
的新分配std::vector
.类似于此的东西:
std::shared_ptr<std::vector<int>> shared_ptr_to_std_vector_of_ints()
{
auto v = std::make_shared<std::vector<int>>();
for (int i = 0; i < 3; i++) v->push_back(i);
return v;
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用基于范围的for循环迭代向量的内容,但它的作用就好像向量是空的.摆弄后,我发现通过将函数返回的值赋给局部变量,然后在循环中引用它,我可以使它按照我的预期运行:
// Executes loop zero times:
std::cout << "First loop:" << std::endl;
for (int i : *shared_ptr_to_std_vector_of_ints()) std::cout << i << std::endl;
// Prints three lines, as expected
std::cout << "Second loop:" << std::endl;
auto temp = shared_ptr_to_std_vector_of_ints();
for (int i : *temp) std::cout << i << std::endl;
Run Code Online (Sandbox Code Playgroud)
剪断打印这个:
First loop:
Second loop:
1
2
3
Run Code Online (Sandbox Code Playgroud)
为什么第一个版本不起作用?
我在macOS Sierra 10.12.6上使用Xcode.我相信它正在使用LLVM 9.0来编译c ++代码.
请注意,shared_ptr_to_std_vector_of_ints
返回按值,因此它返回的是临时的.
基于范围的for循环等效于
{
init-statement
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
Run Code Online (Sandbox Code Playgroud)
这个部分auto && __range = range_expression ;
,就像你的例子一样auto && __range = *shared_ptr_to_std_vector_of_ints() ;
.shared_ptr_to_std_vector_of_ints
返回一个临时的std::shared_ptr<std::vector<int>>
,然后取消引用它以获取std::vector<int>
,然后将其绑定到rvalue-reference __range
.临时std::shared_ptr<std::vector<int>>
将在完整表达式后销毁,并use_count
减少到0,以便std::vector<int>
管理也被销毁.然后__range
成为悬空参考.之后,例如auto __begin = begin_expr ;
将尝试从中获取迭代器__range
,从而导致UB.
(强调我的)
如果range_expression返回临时值,则其生存期将延长到循环结束,如绑定到右值引用所示
__range
,但要注意range_expression中任何临时值的生命周期都不会延长.
正如您的第二个版本所示,问题可以通过使用命名变量来解决; 或者您也可以使用init-statement(来自C++ 20):
for (auto temp = shared_ptr_to_std_vector_of_ints(); int i : *temp) std::cout << i << std::endl;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
576 次 |
最近记录: |