【问题标题】:Range-based loop, unique pointers, and move semantics基于范围的循环、唯一指针和移动语义
【发布时间】:2016-09-22 05:30:13
【问题描述】:

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

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 草案,但没有找到关于该主题的任何说明。

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

【问题讨论】:

  • 您的向量将具有nullptr unique_ptr
  • 您不应该使向量迭代器无效,即调用erase() insert() 等。修改元素非常好。
  • 是的,现在我明白了。谢谢你们的cmets。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:
    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 循环的作用;使用迭代器并为您取消引用它,因此您实际上不会接触迭代器。

    【讨论】:

    • 非常感谢您提供如此详细的回答。现在我脑海中的画面清晰了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多