【问题标题】:C++ 11 - Is moving non local variable safe? [duplicate]C++ 11 - 移动非局部变量安全吗? [复制]
【发布时间】:2015-04-25 14:56:50
【问题描述】:

假设我有一个函数,如下所示:

void a_fct( std::vector<double> &some_vector )
{
  std::vector<double> a_temporary_vector = some_vector;

  ... some stuff involving only a_temporary_vector ...

  some_vector = a_temporary_vector;
}

这当然有点傻,但它只是为了提出以下一般性问题:

  • 在我看来,应该将a_temporary_vector 移动到some_vector 此处,因为它会超出范围。但是将some_vector 移动到a_temporary_vector 而不是复制是否安全?

  • 现在想象一下,在代码的其他地方,我有一个指向作为参数给出的向量的指针。如果我将some_vector 移动到a_temporary_vector,这个指针是否仍然指向它?

在这两种情况下,我是否可以期望它适用于任何 STL 实现?

【问题讨论】:

    标签: c++ c++11 stl move


    【解决方案1】:

    是的,以上所有内容都是绝对安全的。

    移入或移出参数向量确实会改变它,但这就是非常量引用参数无论如何都要做的事情。将临时向量移入到输出参数的结果相当于复制方法。

    指向参数向量的指针也没有问题。 some_vector 仍然是和以前一样的对象,你只是改变了它的内容。

    指针、迭代器和对some_vector 原始数据的引用当然会失效,无论是复制还是移动。

    【讨论】:

    • 好的,谢谢!我认为以某种方式执行... = std::move(some_vector); 正在破坏some_vector 并可能使用先前分配给它的内存。
    【解决方案2】:

    标准(在 17.6.5.15 中)说:

    在 C++ 标准库中定义的类型的对象可以从 (12.8) 中移出。移动操作可以显式指定或隐式生成。除非另有说明,否则此类移出的对象应处于有效但未指定的状态。

    因此,some_vector 在被移出后需要具有(未指定但)有效状态。你可以从它移到你的临时位置,然后再从临时位置移到some_vector

    std::vector<double> a_temporary_vector = std::move(some_vector);
    // do stuff only on a_temporary_vector but not some_vector
    some_vector = std::move(a_temporary_vector);
    

    some_vector 本身的指针和引用仍然有效,但对some_vector 内容的指针或引用无效(正如您在将对象传递给采用非常量引用的函数时通常所期望的那样)。

    注意:在这种情况下,您可以使用 swap,如果您不确定是否要离开它。

    void foo( std::vector<double> &some_vector )
    {
      // swap contents of some_vector into temporary
      std::vector<double> a_temporary_vector;
      a_temporary_vector.swap(some_vector);
    
      // operate on temporary
    
      // swap content back into some_vector
      a_temporary_vector.swap(some_vector);
      some_vector = a_temporary_vector;
    }
    

    【讨论】:

    • 为什么交换比移动更好?
    • @juanchopanza 它不会,我也没有这么说。这只是避免复制向量内容的另一种方式。
    • 好的,所以它不回答问题。
    • @juanchopanza:我包含的旁注没有回答这个问题 - 我认为是真的但不是很引人注目.. :)
    • 好的,谢谢您的详细解答。
    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 2019-06-05
    相关资源
    最近更新 更多