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

Range-based loop, unique pointers, and move semantics

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

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是不合法的。

我 "skimmed" 虽然公开可用的 C++11 草案,但没有找到关于该主题的任何说明。

谁能告诉我上面的代码是否合法?

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

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

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));
}

这就是基于范围的 for 循环所做的;使用迭代器并为您取消引用它,这样您就不会真正接触迭代器。