C++ 移动构造函数
admin
2024-03-04 07:57:52
0

参考链接

rvalue & lvalue
左值引用右值引用
右值引用的好处


左值,右值

左值就是通过变量名指向具体地址的值,如普通变量,指针,和返回值为引用的函数调用;右值就是不指向具体地址的值,如常量,临时变量,计算表达式(的中间结果),返回值不为引用的函数调用。左值在生存期持续存在,而右值要么不存在,要么只是暂时存在。在表达式中,左值可以出现在等号的左右两边,但是右值只能存在于等号的右边

or

C++( 包括 C) 中所有的表达式和变量要么是左值,要么是右值。通俗的左值的定义就是非临时对象,那些可以在多条语句中使用的对象。 所有的变量都满足这个定义,在多条代码中都可以使用,都是左值。 右值是指临时的对象,它们只在当前的语句中有效。
对右值的取地址是错误的,因为内存中不存在这样一块确定的区域;同时,取地址得到的也是右值,如下

int var = 10;
int* bad_addr = &(var + 1); // ERROR: lvalue required as unary '&' operand
int* addr = &var;           // OK: var is an lvalue
&var = 40;                  // ERROR: lvalue required as left operand// of assignment

一般而言,对右值的引用是错误的,如

int &a = 5; // ERROR
std::string& sref = std::string();  // ERROR: invalid initialization of// non-const reference of type// 'std::string&' from an rvalue of// type 'std::string'

这些被称为“左值引用”。非常量左值引用不能分配右值,因为这需要无效的右值到左值转换
可以为常量左值引用分配右值。因为它们是常量,所以不能通过引用修改值,因此不存在修改右值的问题。这使得非常常见的 C++ 习惯用法成为可能,即通过对函数的常量引用来接受值,从而避免了不必要的临时对象复制和构造。

void foo(const string& str);//可以通过以下方法调用
string mystr("123");
foo(mystr);
foo(string("123"));

第二种调用方法就是相当于常量左值引用分配右值


Move constructor

移动构造函数允许将右值对象拥有的资源移动到左值中,而无需创建其副本。

代码示例

class MyString {
private:char* _data;size_t   _len;void _init_data(const char *s) {_data = new char[_len + 1];memcpy(_data, s, _len);_data[_len] = '\0';}
public:MyString() {_data = NULL;_len = 0;}MyString(const char* p) {_len = strlen(p);_init_data(p);}MyString(const MyString& str) {_len = str._len;_init_data(str._data);std::cout << "Copy Constructor is called! source: " << str._data << std::endl;}MyString& operator=(const MyString& str) {if (this != &str) {_len = str._len;_init_data(str._data);}std::cout << "Copy Assignment is called! source: " << str._data << std::endl;return *this;}virtual ~MyString() {if (_data != NULL) {std::cout << "Destructor is called! " << std::endl; free(_data);}}
};int main() { MyString a; a = MyString("Hello"); std::vector vec; vec.push_back(MyString("World")); 
}

运行结果

Copy Assignment is called! source: Hello
Destructor is called!
Copy Constructor is called! source: World
Destructor is called!
Destructor is called!
Destructor is called!

这里调用了两次拷贝构造函数,MyString(“Hello”)和MyString(“World”)都是临时对象,临时对象被使用完之后会被立即析构。这里一共发生了几次内存分配,拷贝,释放呢?a创造时没有发生内存分配,首先临时变量MyString(“Hello”)发生一次内存分配,拷贝过程中有一次内存分配加拷贝,用完之后然后析构释放内存。另一个临时变量也一样。
如果能够直接使用临时对象已经申请的资源,并在其析构函数中取消对资源的释放,这样既能节省资源,有能节省资源申请和释放的时间。 这正是定义转移语义的目的。

通过加入定义转移构造函数和转移赋值操作符重载来实现右值引用(即复用临时对象):

MyString(MyString&& str) { std::cout << "Move Constructor is called! source: " << str._data << std::endl; _len = str._len; _data = str._data; str._len = 0; str._data = NULL;   // ! 防止在析构函数中将内存释放掉}MyString& operator=(MyString&& str) { std::cout << "Move Assignment is called! source: " << str._data << std::endl; if (this != &str) { _len = str._len; _data = str._data; str._len = 0; str._data = NULL;  // ! 防止在析构函数中将内存释放掉} return *this; }

这里引入了右值引用符号&&,运行结果

Move Assignment is called! source: Hello
Move Constructor is called! source: World
Destructor is called!
Destructor is called!

这里就避免了很多不必要的拷贝和分配操作,但是注意,这里临时对象用完之后依然会调用析构函数,所以需要将临时对象的相关地址内存给置为nullptr

所以move constructor的核心是临时变量(右值)的拷贝和赋值

相关内容

热门资讯

疯狂星期六,“免费奶茶”爆了!... 修正一周之后,新一轮的“外卖补贴大战”在本周末重燃战火。 社交媒体上充斥着低价甚至免单的咖啡奶茶订单...
外卖补贴大战重启 “免费奶茶”... 《科创板日报》7月12日讯今日,美团、淘宝闪购等平台再次分别发放外卖大额券,且集中在咖啡茶饮品牌,“...
黄杨树下“00后”干起了“大买... 吉林招募的首批“西部计划”志愿者来到边疆已快一年。图们江畔的黄杨树下,一群没有工作经验的“00后”,...
原创 幽... 1、新手裱花师的奇幻首秀 店里新来了个学徒小宇,第一天学裱花,戴着手套的手紧张得直抖。师傅让他先练挤...
跟朋友一起吃北京传统小吃门钉肉... 跟朋友一起吃北京传统小吃门钉肉饼,皮薄馅大多汁、一口一个真爽。
原创 麻... 材料准备 宽粉 200克 芝麻酱 2大勺 生抽 1大勺 香醋 1小勺 蒜末 1茶匙 小葱 适量 辣椒...
黑管 有叫什么? 黑管 有叫什么?clarinet 单簧管
请问…… 请问……设有x排,每排有y盆。则x*y=24 且 3
心理学家会不会预判人的行为? 心理学家会不会预判人的行为?心理学家应该是可以预判人的行为,因为他对人的心理的一些想法都有了一些判断...
续写句子。每个人的青春只有一次... 续写句子。每个人的青春只有一次青春是用来奔跑奋斗的是篮球场上那一个个跳跃?是用来探索未知的领域,是攀...
《永不消逝的电波》是一部怎样的... 《永不消逝的电波》是一部怎样的经典片?《永不消逝的电波》是一部经典的谍战片,地下工作者的机智勇敢和大...
异星战场是什么意思,卡特的死是... 异星战场是什么意思,卡特的死是怎么回事异星战场:根据剧情,是猪脚卷入外星的一场大战。 卡特没有死...
想看打篮球的直播,哪里能看? 想看打篮球的直播,哪里能看?想看打篮球的直播,哪里能看?44分钟506路 北塘指挥部上车 | 步行8...
为什么会讨厌香菜 为什么会讨厌香菜很讨厌.一丁点香菜都受不了. . 但我身边的人都很喜欢.貌似只有我一个严重讨厌 ...
原形毕露是什么意思 原形毕露是什么意思原形毕露意思是指本来面目完全暴露,指伪装被彻底揭开。出自何其芳《理性与历史》,成语...
你们有谁知道这文啥名字么,一个... 你们有谁知道这文啥名字么,一个综童话,男主受穿越到童话世界,遇见了长着两个尾巴的美人鱼(男),安全第...
QwQ寻动漫,男主女主全程秀恩... QwQ寻动漫,男主女主全程秀恩爱QwQ最好是温馨感人的QwQ不要虐的,咱泪点超低,看到虐的就会哭的稀...
找一本书忘了名字,只记得男主穿... 找一本书忘了名字,只记得男主穿越到异世界一对姐弟的弟弟身上,之前也是很厉害的一个人唐异在异界?奇幻英...
请问古典吉他曲有什么比较经典好... 请问古典吉他曲有什么比较经典好听的谱吗?有啊~五月天的《知足》我个人觉得《天空之城》《卡农》《梦中婚...
我的世界怎么造水下秘密基地 我的世界怎么造水下秘密基地方案1:如果你有耐心,可以在不深的区域就地面搭起五面面水的密封建筑,最顶端...