我新的C++ 11和写了下面的代码来了解std::move
是如何工作的:了解移动构造函数,的std ::移动和析构函数
#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
的所有权将完全转移到队列中,并且不应在其所有权转移期间调用它们的析构函数。
所以我的问题是:
- 当我看到被释放两次的情况下,这是否意味着它执行复制而不是移动?
- 如果上面的答案是肯定的,那么我怎样才能真正避免复制?
谢谢
因此,如果我的对象有成员指针,并且它的析构函数将释放这些指针。这是否意味着我无法真正移动这些对象? – keelar
@keelar你可以 - 当你从它移动时,只需设置指向'nullptr'的指针。在空指针上执行delete操作将不起作用。在实现移动构造函数/赋值运算符时,应该使对象保持有效(但不确定)状态。 –
非常感谢!这听起来很完美。我能否进一步知道'= default'移动构造函数/赋值是否将'nullptr'赋值给源成员指针?或者我应该开发自己的移动构造函数/任务? – keelar