[英]using shared_ptr to std::vector in range-based for loop
我編寫了一個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;
}
我嘗試使用基於范圍的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;
剪斷打印這個:
First loop:
Second loop:
1
2
3
為什么第一個版本不起作用?
我在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
}
}
零件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
變成__range
參考。 之后例如auto __begin = begin_expr ;
會嘗試從__range
獲取迭代器,這會導致UB。
(強調我的)
如果range_expression返回臨時值,則其生命周期將延長到循環結束,如綁定到右值引用
__range
,但要注意__range
中任何臨時值的生命周期都不會延長。
正如您的第二個版本所示,問題可以通過使用命名變量來解決; 或者您也可以使用init-statement(來自C ++ 20):
for (auto temp = shared_ptr_to_std_vector_of_ints(); int i : *temp) std::cout << i << std::endl;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.