c++ - 了解 move 构造函数、std::move 和析构函数

标签 c++ c++11 destructor move

我是 c++11 的新手,写了下面的代码来理解 std::move 是如何工作的:

#include <queue>
#include <stdio.h>

class X {
 public:
  X(int x) : x_(x) {}
  ~X() {
    printf("X(%d) has be released.\n", x_);
  }

  X(X&&) = default;
  X& operator = (X&&) = default;

  X(const X&) = delete;
  X& operator = (const X&) = delete;
 private:
  int x_;
};


int main() {
  std::queue<X> xqueue;
  for (int x = 0; x < 5; ++x) {
    xqueue.push(std::move(X(x)));
  }
  return 0;
}

但是,它会生成以下输出,这表明每个 X(n) 的析构函数都被调用了两次:

X(0) has be released.
X(1) has be released.
X(2) has be released.
X(3) has be released.
X(4) has be released.
X(0) has be released.
X(1) has be released.
X(2) has be released.
X(3) has be released.
X(4) has be released.

我可以想象第二轮输出恰好发生在 main() 函数的末尾,而第一轮可能发生在那些中间 X 的循环中超出范围。

但是,我认为此类中间 X 的所有权将完美地转移到队列中,并且在所有权转移期间不应调用它们的析构函数。

所以我的问题是:

  1. 当我看到一个实例被释放两次时,这是否意味着它执行复制而不是 move ?
  2. 如果以上答案是肯定的,那我怎样才能真正避免抄袭呢?

谢谢,

最佳答案

如果你从一个物体 move 到另一个物体,你仍然总共有两个物体。他们都需要被摧毁。也许 move 是一个有点误导性的术语,但不是对象本身从一个地方 move 到另一个地方(对象实际上从未 move 过)——而是对象的内容。

  1. 没有。如上所述, move 不会消失其中一个对象。从一个对象到另一个对象的复制和 move 都将涉及两个对象。区别在于它们对对象的影响。拷贝当然会将一个对象的成员复制到另一个对象。另一方面, move 会将成员从一个对象 move 到另一个对象 - 通常是更快的操作。
  2. 不适用

关于c++ - 了解 move 构造函数、std::move 和析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21767066/

相关文章:

c++ - 如何在另一个对象的构造函数中声明和创建对象?

c++ - 使用 RAW 指针对 boost::shared_ptr 变量进行条件初始化

C++ 11:std::thread池化?

c++ - 由于抛出异常而检测析构函数何时运行?

C++ 析构函数过早地删除东西(对象、指针?)

c++ - 在抛出的异常中销毁临时字符串

c++ - 如何使函数模板仅适用于特定命名空间中的类型?

C++ 是否应该在设置新对象时销毁对象中的旧对象?

C++ 访问冲突类数组

c++ - 获取对模板参数给定类型对象的虚拟引用