1.1 Motivation for Move Semantics

本文深入探讨了移动语义的重要性,特别是在资源节约方面的优势,并通过C++03标准下的示例代码详细解析了移动语义前后对象的生命周期及内存管理的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Motivation for Move Semantics

为什么我们需要移动语义呢?
节约资源
就是这四个字 节约资源

2.C++03

①函数 createAndInsert();

#include <string>
#include <vector>
std::vector<std::string> createAndInsert()
{
std::vector<std::string> coll; // 创建了一个元素是string的vector

coll.reserve(3); // 预留了三个对象的空间

std::string s = "data"; // 创建一个string 对象 初始化为data

coll.push_back(s); // 插入string对象s

coll.push_back(s+s); // 插入右值string对象 

coll.push_back(s); // 插入string 对象s

return coll; // 返回这个vector
}

②main函数中的调用

int main()
{
std::vector<std::string> v; // 创建一个空的 元素的string的vector
...
v = createAndInsert(); // 把返回的vector 赋值给v
...
}

我们来分析一下在这个过程当中 发生了什么
①std::vector< std::string> v;
在栈中创建了一个vector对象,它有0个元素,所以堆中没有为元素分配空间
②v = createAndInsert();
然后进行了函数调用
③std::vectorstd::string coll;
在栈中创建了一个vector对象,它有0个元素,所以堆中没有为元素分配空间
④coll.reserve(3);
提前在堆中预留出一块并未初始化的空间,size仍为0

现在我们有了在栈中有了三个对象 v coll s, 其中两个在堆中分配了内存

⑤std::string s = “data”;
我们在栈中创建了一个string对象s,指向堆中的数据"data"
⑥coll.push_back(s);
在堆中创建一个s指向的字符串"data"的副本,然后coll的第一个元素去指向该字符串 也就是说这个是一次深拷贝
⑦coll.push_back(s+s);
我们知道函数传参,是进行完表达式求值以后,在传入
s+s会生成一个新的字符串对象Temp,这个Temp在栈中,它指向堆中的字符串"datadata";
然后将这个Temp传递给形参,在堆中创建一个Temp指向的字符串的副本,然后coll的第二个元素去指向这个字符串 这也是一个深拷贝
然后Temp是一个临时对象,也就是一个右值,此时它的使命已经完成了
所以我们需要销毁他,以及它所指向的字符串
⑧coll.push_back(s);
在堆中创建一个s指向的字符串"data"的副本,然后coll的第三个元素去指向该字符串 也就是说这个是一次深拷贝
⑨return coll;
这里是return by value
所以会发生什么呢?先把s销毁了
然后呢在堆中对coll进行深拷贝,所有的元素都拷贝一份,然后v去指向它,然后销毁coll。
这里也有可能是把coll变成一个右值,返回给v,销毁右值,看编译器的
VS2019是直接析构coll,然后以右值的方式传给v

class Test
{
public:
     Test() { cout<<"无参构造函数" << endl; }
     ~Test(){ cout << "析构函数" << endl; }
};


Test Fun(void)
{
     Test a;

     return a;
}


int main()
{
     Test a;

     
     a = Fun();
     return 0;
}

按照道理来说,创建了两个对象,只析构两次,但是多了一次,那就是作为右值,可以拿出更具说服力的代码

Test& operator=(Test Temp)
 { cout << "重载赋值运算符" << endl; return Temp; }
这个参数可以接受右值 也可以接受左值

Test& operator=(Test& Temp) 
{ cout << "重载赋值运算符" << endl; return Temp; }
只能接受左值

当把第二种重载赋值运算符的时候,就报错了
完整代码,仅做测试 代码写的不规范

class Test
{
public:
     Test() { cout<<"无参构造函数" << endl; }
     ~Test(){ cout << "析构函数" << endl; }
     Test(const Test& a) { cout << "拷贝构造函数" << endl; }
     Test& operator=(Test Temp) 
     { cout << "重载赋值运算符" << endl; return Temp; }
};


Test Fun(void)
{
     Test a;

     return a;
}


int main()
{
     Test a;

     
     a = Fun();



     return 0;
}

在这里插入图片描述

3.C++11

我们放到下一节去讲,这节写的有点多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值