C++11的更新内容--左值引用--1114
创始人
2024-01-21 09:29:43
0

1 初始化相关

1.1 {}初始化

C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自 定义的类型。

struct Point
{int _x;int _y;
};
class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){cout << "Date(int year, int month, int day)" << endl;}
private:int _year;int _month;int _day;
};
int main()
{//内置类型比如intint x1 = 1;int x2={ 2 };//数组int array1[]{ 1, 2, 3, 4, 5 };int array2[5]{ 0 };//自定义类型 Point p{ 1, 2 };Date d1(2022,11,14);//用构造函数初始化Date d2{2022,11,14};//列表初始化// C++11中列表初始化也可以适用于new表达式中int* pa = new int[4]{ 0 };return 0;
}

1.2 std::initializer_list

C++11中对{1,3,4}这样的列表定义了一个新的类型  --  initializer_list

auto il = { 10, 20, 30 };

cout << typeid(il).name() << endl;

 并在库中的容器的里支持了用initializer_list支持的构造函数。vector、list、map等都可以用它进行初始化。

vector v = { 1,2,3,4 };

list lt = { 1,2 };

map dict = { {"sort", "排序"}, {"insert", "插入"} };

2 声明

2.1 auto

自动推断类型。

2.2 decltype

关键字decltype将变量的类型声明为表达式指定的类型。

int main()
{const int x = 1;double y = 2.2;decltype(x * y) ret; // ret的类型是doubledecltype(&x) p;      // p的类型是int*cout << typeid(ret).name() << endl;cout << typeid(p).name() << endl;return 0;
}

2.3 nullptr

3 新增容器

array --->静态数组

forward_list --->单链表

unordered_map --->哈希表

unordered_set --->哈希表

4 右值引用和移动语义

4.1 左值和右值

左值:可以取它的地址的就是左值。(左值除了被const修饰的 其余都可以修改)

右值:不能出现在赋值运算符左边的,不能被取地址的。

例如:字面常量、表达式返回值、函数返回值等。        

                10          x+y        func(x,y)

 4.2 右值引用

int main()
{10;x + y;Func(x, y);int&& rr1 = 10;double&& rr2 = x + y;double&& rr3 = Func(x, y);
}

 tip:右值不能被获取地址,但是一旦被引用之后,就可以通过对引用的取地址/修改来影响右值。但这不是重点。

无论左值引用还是右值引用,都是给对象取别名。

4.3 左值引用和右值引用的比较

左值引用只能引用左值,不能引用右值。但左值引用加了const后就可以引用右值了。

const int& ra3 = 10;

右值引用只能引用右值,不能引用左值。但是可以引用move后的左值。

int&& r3 = std::move(a);

 4.4右值引用的使用场景

之所以使用左值引用,目的是:

1、减少函数参数调用以及做返回值时的拷贝构造,以提高效率。

2、做输出型参数,修改返回对象。

短板:但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回, 只能传值返回

在我们以前的实现中,当我的返回值类型非常复杂时,比如vector> 或者是 红黑树、哈希表时,消耗仍然大。既然我们这个临时变量马上就要析构,C++11对于此方面进行了右值引用的优化方案。

拿一个string类进行说明。主要关注对象是移动构造、和移动拷贝

namespace chy
{class string{public:string(const char* str = ""):_size(strlen(str)), _capacity(_size){_str = new char[_capacity + 1];strcpy(_str, str);}// 拷贝构造string(const string& s):_str(nullptr){cout << "string(const string& s) -- 拷贝构造(深拷贝)" << endl;string tmp(s._str);swap(s);/*_str = new char[s._capacity+1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;*/}// 移动构造string(string&& s):_str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 资源转移" << endl;swap(s);}// 拷贝赋值string& operator=(const string& s){cout << "string& operator=(string s) -- 拷贝赋值(深拷贝)" << endl;string tmp(s);swap(tmp);return *this;}// 移动赋值string& operator=(string&& s){cout << "string& operator=(string s) -- 移动赋值(资源移动)" << endl;swap(s);return *this;}void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}private:char* _str;size_t _size;size_t _capacity;};
}

针对于返回值的测试用例

bit::string to_string(int value)
{bool flag = true;if (value < 0){flag = false;value = 0 - value;}bit::string str;while (value > 0){int x = value % 10;value /= 10;str += ('0' + x);}if (flag == false){str += '-';}std::reverse(str.begin(), str.end());return str;
}

由于我们实现移动赋值和移动拷贝,这两个函数的参数是右值引用。

移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己。

当我们调用to_string()函数时,编译器会将其的返回值识别成右值,从而调用类型最匹配的移动拷贝。如果没实现移动构造和移动赋值,那依然走的是深拷贝。

int main() {

chy::string ret; ret=to_string(-3456); //移动赋值

chy::string ret2=chy::to_string(-1234);//移动拷贝

return 0;   

 }

 一些例子

int main()
{//chy::string str1("hello");//拷贝构造//chy::string str2(str1); //  拷贝构造//chy::string str3(move(str1)); // 移动构造std::string s1("hello world");//拷贝构造std::string s2(s1); // 拷贝构造// std::string s3(s1+s2);std::string s3 = s1 + s2; // 移动构造std::string s4 = move(s1);//移动构造return 0;
}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...