移动构造函数如何在 C++ 中工作?

How move constructor works in C++?

我已经阅读了很多关于移动构造函数的文章(甚至在堆栈上),但我没有在任何地方找到关于它如何工作的确切解释(如果这个临时变量及其地址如何转移指针到临时对象并保存遇到")" ).

这是一个简单的例子

#include <iostream>
#include <vector>
using namespace std;
class boVector {
private:
    int size;
public:
    boVector() {};
    boVector(const boVector& rhs) { cout << "copy Ctor." << endl; }
    boVector(boVector&& rhs) { cout << "move Ctor." << endl; }
};

void foo(boVector v) {}
boVector createBoVector() { return boVector(); }

int main()
{
    //copy
    boVector reausable = createBoVector();
    foo(reausable);
    //move
    foo(std::move(createBoVector()));
    return 0;
}

都说move Ctor是浅拷贝或者指针赋值。但是我如何用一个指向临时对象的指针来启动我的对象(当这个对象被销毁时,我的对象将指向一个未知的地址,从我的角度来看这是无效的)。

用他遇到“)”后指针地址不存在的变量初始化是不对的。

如果有人能解释一下这个临时变量在内存中的样子,以及如何将临时对象的地址分配给我当前的对象,并且这个操作是有效的。

A "move constructor" 没什么神奇的 - 它是一个采用 rvalue 引用的构造函数.

Rvalue 引用 绑定到临时对象,并具有即将过期且以后不会在程序中访问的内容的 "meaning":this使开发人员能够根据指针交换或类似的快速操作实现资源持有 classes 的移动。

您的 boVector class 无法真正利用移动语义,因为它仅存储 int 并且不包含任何资源。移动 int 与复制一样快。


foo(std::move(createBoVector()));

表达式,std::move 是多余的,因为 createBoVector() 已经是一个 rvalue.


考虑:

foo(createBoVector());

这将调用 boVector(boVector&&),因为它比 boVector(const boVector&) 更匹配。

createBoVector() 创建的实例将在表达式的整个持续时间内存在 - 这意味着 右值引用 将在整个持续时间内指向有效对象boVector(boVector&&).

All say that a move Ctor is a shallow copy copy or just a pointer assignment.

并非所有人都这么说,因为事实并非如此。移动构造函数就是您定义它的样子。在您的示例中,您的 move ctor 完全做了其他事情。移动构造函数(与复制构造函数相反)的要点是您知道另一个对象即将被销毁,因此您可以蚕食或移动它的资源。

移动构造函数 可以 生成 "shallow copy",尽管该术语在 C++ 中是口语化的而不是明确定义的。 "Just a pointer assignment" - 也许,可能,有时。

But how can i initiate my object with a pointer to a temporary object (when this object will be destroy my object will point to an unknown address and this is not valid from my point of view).

您(通常)不会使用 T* 类型的指针来初始化 T 类型的对象本身。您可以分配 my_t = *my_t_ptr,或者如果您知道可以 "cannibalize" my_t_ptr 指向的 T,因为它很快就会被删除,那么您可以分配 my_t = std::move(*my_t_ptr).

Can you give me a more relevant example [of a meaningful difference between a move constructor and a copy constructor]...?

"classical" 示例是当您的 T 是通过在堆上分配一些 space 来构建的。当你从另一个复制构造一个 T 时,你别无选择,只能分配第二段内存;当你移动构造一个 T 时,你可以:1。将指针从现有的T复制到正在建设的T。 2. 将现有T的成员指针设置为nullptr。在这种情况下,您只能使用一个 T 的堆栈 space.