我是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
的所有权将完美地转移到队列中,并且在所有权转移期间不应该调用它们的析构函数。
所以我的问题是:
谢谢,
答案 0 :(得分:5)
如果从一个对象移动到另一个对象,则总共还有两个对象。它们都需要被摧毁。也许move
是一个有点误导性的术语,但不是对象本身从一个地方移动到另一个地方(物体从未实际移动) - 它是对象的内容。
答案 1 :(得分:1)
移动构造函数窃取对象的属性/成员并将其提供给新对象。因此,在您的示例中,当移动构造函数的作用域结束并且现在空对象被销毁时,会发生第一组delete语句。
第二组delete语句在队列中新创建的对象被销毁时发生
另外值得注意的是,如果删除的对象的属性不是POD类型,那么在delete方法中访问它们不是一个好主意,否则会导致seg错误