初学者的问题:
Class Quote {
public:
/* ..... */
virtual Quote* clone() const & {return new Quote(*this);}
virtual Quote* clone() && {return new Quote(std::move(*this));} // (***)
/* ..... */
}
new 分配的对象位于免费商店中。 * 此 是调用 clone() 的任何对象,并且不一定是动态分配的对象。
如果移动和移动的对象位于不同的内存区域,移动机制如何工作?或者也许他们从来没有真正处于不同的领域,我错过了什么?
据我所知,移动构造函数创建了新的开销,链接到移动对象的数据/内存部分。数据本身不会移动/更改。在上述情况下,这是如何工作的?如果它以相同的方式工作,那么在 新 运行之后我们就不会有一个动态分配的对象,它位于免费商店之外(无论 * 这个地方 位于?)这是以某种方式解决的 std :: move() ?我不确定 std :: move() 是如何工作的,除了它强制 - 返回对命名对象的rvalue引用,使得可以从那里移动对象
答案 0 :(得分:1)
根据我的理解,移动构造函数会创建新的开销 链接到移动对象的数据/内存部分。数据 本身不会被移动/改变。
不正确。一个典型的移动构造函数((我强调典型的因为移动构造函数可以真正做任何类编写者想要它做的事情)将“窃取”另一个对象拥有的资源< em>(例如动态分配的数组),通过重新分配句柄(例如指向动态分配的数组的指针)
当我说资源是远程拥有的时,我的意思是它实际上并不是该类的数据成员。但是,句柄是类的数据成员。句柄指的是资源。移动到对象和从对象移动具有不同的地址和数据成员。他们的数据能够有效地移动,因为它实际上不是类的一部分,它由句柄引用。与资源不同,句柄很小,复制起来很便宜。 “移动”实际上是将句柄从源对象复制到目标对象,然后使源对象中的句柄无效,以便其析构函数不会破坏资源。
如果移动和移动到移动机制,移动机制如何工作 对象在不同的内存区域?
(我再说一下典型的移动构造函数)这是无关紧要的。无论它们碰巧存储在何处,它们仍然具有相同的存储器布局。手柄的修改完全相同。当调用移动对象的析构函数时,将释放资源(除非该对象也被移动)。这意味着当对象超出范围时,如果它在堆栈上,或者在指向它的指针上调用delete
时,如果它在免费存储上。 (还有其他可能性,但这两种显然是最常见的)
答案 1 :(得分:0)
移动不会移动所有内容。例如,int和指针等内置数据类型无法移动,只能复制它们。移动是纯粹的语义。最好的例子是std::vector
或std::string
。两者通常都包含指向某些动态分配的内存和一些其他变量的指针。所述内存在语义上属于vector
对象,这意味着它必须释放内存,它可以改变其内容,它可以控制它,并且是唯一一个这样做的。常用术语是“已分配内存的vector
具有所有权”
现在,当您复制向量时,原始文件将保留该所有权,并且副本将必须分配它自己的内存。相反,当你移动一个向量时,允许移动构造的新向量窃取分配的内存,接管原始向量曾经构成的资源的所有权。这可以做到,因为原始矢量无论如何都要超出范围,并且它不再需要该资源
但是,移动的vector
的实际数据成员不会自行移动。由于它们是指针并且可能是整数,因此它们只能被复制。完成之后,原始中的指针和整数以语义结束其分配的内存所有权的方式进行更改。
简而言之:移动是一种语义的东西,在较低的技术层面上,它主要是一个副本并将原始设置为零。