【问题标题】:Iterating over dereferenced unique_ptr, that contains vector, in for range loop在 for range 循环中迭代包含向量的取消引用的 unique_ptr
【发布时间】:2018-05-31 21:54:07
【问题描述】:

为什么这段代码没有像我想象的那样工作?

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

向量对象在执行循环的第一次迭代之前被销毁

【问题讨论】:

  • 请注意,C++20 允许通过“带有初始化程序的基于范围的语句”来避免这种陷阱,如下所述:herbsutter.com/2017/11/11/…。也就是说:您将单独声明unique_ptr,确保它在整个循环中都存在,然后使用它的取消引用作为迭代的范围。
  • 为什么不直接写for (auto it: {1, 2, 3, 4, 5}) 呢?对于更复杂的情况,为什么要使用std::unique_ptr&lt;std::vector&lt;T&gt;&gt; 而不是std::vector&lt;T&gt;
  • 是的,这是一个非常人为的例子,它展示了问题区域,但有点夸张。 :)

标签: c++ c++11 for-loop vector unique-ptr


【解决方案1】:

range-based for loop 相当于:

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

对于您的 range_expression,它将是

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

但是

如果 range_expression 返回一个临时值,它的生命周期会延长到循环结束,如绑定到右值引用 __range 所示,但请注意 中任何临时值的生命周期>range_expression 未扩展。

std::make_unique 返回的是一个临时的std::unique_ptr,在完整表达式之后它将被销毁。这意味着它所管理的std::vector 也将被销毁;即使从临时std::unique_ptr 得到的std::vector 绑定到转发引用,它的生命周期也不会延长。

从 C++20 开始,您可能会使用 init-statement;比如

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;

【讨论】:

  • 从该页面:“如果 range_expression 返回一个临时值,它的生命周期将延长到循环结束,如绑定到右值引用 __range 所示,但请注意range_expression 中的任何临时文件都不会被扩展。"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 2019-02-11
  • 2015-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多