2017-12-18 334 views
9

为什么不按照我的假设工作?迭代包含向量的解除引用unique_ptr,用于范围循环

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

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

+1

注意,C++ 20允许避免经由“基于范围与初始化语句”这种缺陷的,如下所述:https://herbsutter.com/2017/11/11/行程报告下落-ISO-C-标准的会议阿尔伯克基/。也就是说:你将独立地声明'unique_ptr',确保它在整个循环中生存,然后使用它的取消引用作为迭代的范围。 –

+1

为什么不简单写'for(auto it:{1,2,3,4,5})'?对于更复杂的情况,为什么'std :: unique_ptr >'而不是'std :: vector ''。 – Jarod42

+0

是的,这是一个非常人为的例子,它展示了问题领域,但有点夸张的方式。 :) –

回答

11

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语句;如

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; 
+1

从那个页面:“如果'range_expression'返回一个临时的,它的生命周期被扩展到循环结束,如绑定到右值引用'__range'所指示的那样,但要注意'range_expression中任何临时的生命周期'不延长。“ – 0x5453

+0

这是粘性语法糖,谢谢 – Daniil