簡體   English   中英

在基於范圍的for循環中使用shared_ptr到std :: vector

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM