0

初学者的问题:

Class Quote {
    public:
    /* ..... */

    virtual Quote* clone() const & {return new Quote(*this);}

    virtual Quote* clone() && {return new Quote(std::move(*this));} // (***)

    /* ..... */
}

由new分配的对象在 free-store 中。*是调用clone()的任何对象,不一定是动态分配的对象。

如果移动对象和移动对象位于不同的内存区域,移动机制如何工作?或者也许他们从来没有真正在不同的领域,我错过了什么?

据我了解,移动构造函数创建了新的开销,这些开销链接到被移动对象的数据/内存部分。数据本身不会移动/更改。在上述情况下这是如何工作的?如果它以相同的方式工作,那么在运行之后,我们不会有一个动态分配的对象位于自由存储之外(无论*位于何处?)这是否由std::move()以某种方式解决?我不完全确定std::move()如何/为什么工作,除了它强制返回对命名对象的右值引用,从而可以从该对象移动。

4

2 回答 2

1

据我了解,移动构造函数创建了新的开销,这些开销链接到被移动对象的数据/内存部分。数据本身不会移动/更改。

不对。通过重新分配句柄例如指针_到动态分配的数组)

当我说资源是远程拥有的时,我的意思是它实际上不是该类的数据成员。然而,句柄该类的数据成员。句柄指的是资源。移至对象和移出对象具有不同的地址和数据成员。它们的数据能够有效地移动,因为它实际上不是类的一部分,而是由句柄引用的。与资源不同,句柄很小,复制起来也很便宜。“移动”实际上是将句柄从源对象复制到目标对象,然后使源对象中的句柄无效,以便其析构函数不会破坏资源。

如果移动对象和移动对象位于不同的内存区域,移动机制如何工作?

(我又说的是典型的移动构造函数)这无关紧要。无论它们碰巧存储在哪里,它们仍然具有相同的内存布局。手柄修改完全相同。当移动到对象的析构函数被调用时,资源将被释放(除非该对象也被移动)。这意味着当对象超出范围时,如果它在堆栈上,或者在delete指向它的指针上调用时,如果它在自由存储上。(还有其他可能,但这两种显然是最常见的)

于 2013-11-15T09:30:59.930 回答
0

一动不动一切。例如,整数和指针等内置数据类型不能移动,只能复制。移动是纯粹的语义。最好的例子是 astd::vector或 a std::string。两者通常都包含指向一些动态分配的内存和一些其他变量的指针。所述内存在语义上属于vector对象,这意味着它必须释放内存,它可以更改其内容,它可以控制它并且是唯一这样做的。常用术语是“vector拥有分配内存的所有权”。
现在,当您复制向量时,原始向量将保留该所有权,而副本将不得不分配它自己的内存。相反,当你移动一个向量,移动构造的新向量被允许窃取分配的内存,接管原始向量曾经拥有的资源的所有权。可以这样做是因为原始向量无论如何都将超出范围,并且它不再需要该资源。
但是,被移动的实际数据成员vector本身并没有被移动。因为它们是指针,也可能是整数,所以它们只能被复制。完成此操作后,原始指针和整数会以语义上结束其对已分配内存的所有权的方式进行更改。

简而言之:移动是一种语义的东西,在较低的技术层面上,它主要是一个副本并将原件设置为零。

于 2013-11-15T10:05:41.623 回答