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