Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over dereferenced unique_ptr, that contains vector, in for range loop

Why doesn't this code work as I supposed?

for (auto it: *std::make_unique<std::vector<int>>(std::vector<int>({1, 2, 3, 4, 5})))
    std::cout << it << std::endl;

The vector object is destroyed before executing the first iteration of the loop

like image 454
Daniil Avatar asked Feb 04 '23 03:02

Daniil


1 Answers

The range-based for loop is equivalent to:

{
  init-statement
  auto && __range = range_expression ;
  ... 
} 

For your range_expression, it would be

auto && __range = *std::make_unique<std::vector<int>>(std::vector<int>({1, 2, 3, 4, 5}));

But

If range_expression returns a temporary, its lifetime is extended until the end of the loop, as indicated by binding to the rvalue reference __range, but beware that the lifetime of any temporary within range_expression is not extended.

What std::make_unique returns is a temporary std::unique_ptr, after the full-expression it will be destroyed. That means the std::vector managed by it would be destroyed too; even though the std::vector got from the temporary std::unique_ptr is bound to the forwarding reference, its lifetime won't be extended.

From C++20 you might work around using init-statement; such as

for (auto p = std::make_unique<std::vector<int>>(std::vector<int>({1, 2, 3, 4, 5})); auto it : *p)
    std::cout << it << std::endl;
like image 61
songyuanyao Avatar answered Feb 08 '23 16:02

songyuanyao