基于范围的循环,唯一指针和移动语义

时间:2016-05-24 20:19:03

标签: c++ c++11 move-semantics unique-ptr

这是一个类似于我的代码:

for (auto &uptr : vector_of_unique_ptrs) {              // 1
  auto result = do_the_job_with_pointee(uptr.get());    // 2
  record_intermidiate_result(result, std::move(uptr));  // 3
}

这里有一些指向某些对象的独特指针(第1行)。

我遍历向量(第1行)并使用指针对象(第2行)做一些工作。

工作完成后,我需要取一个结果并将所有权转移到其他地方(第3行)。

代码编译和执行没有任何问题,但我觉得在迭代期间移动iteratee是不合法的。

我通过公开发布的C ++ 11草案“撇去”,但没有找到任何有关该主题的说明。

有人可以告诉我上面的代码是否合法?

2 个答案:

答案 0 :(得分:10)

您的代码绝对合法且定义明确。没有什么能阻止你在迭代过程中修改序列的元素,移动只是一种修改形式。

请记住,不要在循环后尝试使用这些指针。

答案 1 :(得分:5)

for (auto &uptr : vector_of_unique_ptrs)

' uptr'现在是对你制作的任何类型的unique_ptr的引用。 ' uptr'在这种情况下,它不是迭代器。因此,您的代码是安全的,因为它实际上并没有弄乱迭代器。

现在,如果您编写了这样的代码:

for(auto iter = vec.begin(); iter != vec.end(); iter++)

这将是一个不同的故事。在这个' iter'上使用std :: move在循环中间会有问题,可能不是你想要的。但就向量和循环而言,使用代码是安全的。实际上,这里有几种查看代码的方法:

//I'm calling your vector_of_unique_ptrs 'vec' for brevity
//and I'm assuming unique_ptr<int> just 'cause

//This works
for (auto iter = vec.begin(); iter != vec.end(); iter++) {
  unique_ptr<int>& uptr = *iter;
  auto result = do_the_job_with_pointee(uptr.get());
  record_intermidiate_result(result, std::move(uptr));
}

//As does this
for (size_t i = 0; i < vec.size(); i++) {
  unique_ptr<int>& uptr = vec[i];
  auto result = do_the_job_with_pointee(uptr.get());
  record_intermidiate_result(result, std::move(uptr));
}

这就是基于范围的循环所做的事情;使用迭代器并为您取消引用它,这样您就不会实际触摸迭代器。