• C++11(第一篇)【C/C++复习版】


    目录

    1、统一的列表初始化

    2、所有容器新增initializer_list构造

    3、auto、decltype和typeid

    4、nullptr 

    5、 范围for

    6、STL中的变化

    array(新容器)

     forward_list(新容器)

     cbegin、cend、crbegin、crend(新方法)

    7、右值引用和移动语义(重点)

    1)什么是左值?什么是左值引用?

    2)什么是右值?什么是右值引用?

     3)什么是移动拷贝/赋值

     4)move

    8、完美转发

    右值引用和左值引用本身是左值还是右值? 

    万能引用


    1、统一的列表初始化

    一切皆可以用{}初始化,且 = 可以不写 

    2、所有容器新增initializer_list构造

    注意:这两句代码用的不是同一个语法。

    第一句代码是用initializer_list实现的,它是用一个常量数组构造一个initializer_list(原理是它有两个指针,指向数组空间的开始和结束位置),C++11里vector里实现了以initializer_list为参数的构造函数

    第二句才是前面提到的列表初始化。

    所有容器都实现了以initializer_list为参数的构造函数,都可以用上面的写法。

    3、auto、decltype和typeid

    1)auto可以进行类型推导,函数指针也可以用auto来定义推导。 

    2)但如果我只是想声明一个变量,那么可以用decltype。

    decltype(pf1)pf2;这句代码就是推导出pf1的类型然后用这个类型定义一个pf2。

    decltype可以用来定义变量,也可以用来做模板实参,就是当一个类型用。

    3)typeid也可以推导类型,但它只能打印来看,不能用。

    4、nullptr 

    nullptr也是C++11的,因为NULL在C语言里被定义成字面量0,会有一些歧义,所以有了nullptr。        

    5、 范围for

    范围for循环通过遍历给定容器的begin()和end()函数返回的迭代器范围,来遍历容器中的每一个元素。用的比较多,不多讲了。

    6、STL中的变化

    array(新容器)

    相当于静态数组增加了一个越界检查功能。

     forward_list(新容器)

    单链表,不支持尾插尾删,insert,erase也只支持了after。比较鸡肋。

     cbegin、cend、crbegin、crend(新方法)

    返回const迭代器。

    7、右值引用和移动语义(重点)

    1)什么是左值?什么是左值引用?

    左值是一个数据的表达式(如变量名或解引用的指针),我们可以获取它的地址,一般可以对它赋值,只有左值可以出现在赋值符号的左边,右值不行。左值引用就是对左值的引用,给左值取别名,左值引用的符号是&。

    左值引用的使用价值:减少拷贝

    1、做参数        2、做返回值     

    但左值引用一直没有解决的问题是局部变量无法通过左值引用返回。  

    2)什么是右值?什么是右值引用?

    右值不能取地址,一般是在赋值符号右边,但不能出现在赋值符号左边。对右值取别名就是右值引用,右值引用的符号是&&。

    内置类型的右值叫纯右值,自定义类型的右值叫将亡值

    下面两个函数构成重载吗?

    答案是构成,虽然两个函数都能用,但编译器会调用更匹配的那个,也是就第二个func,如果没有第二个func,第一个也行。

     3)什么是移动拷贝/赋值

    对于右值将亡值,可以通过交换两个对象的资源来减少拷贝。对于下面的例子,加上编译器做出优化,虽然str是左值,但由于它出了作用域就销毁了,编译器会识别str是右值将亡值,然后调用右值引用的拷贝构造,即移动拷贝。

    string& operator=(string && s) 和 string& operator=(const string & s)构成重载,如果是右值的拷贝构造,就调用第一个,否则调用第二个

    需要深拷贝的类,才需要实现移动赋值。

     4)move

     move可以理解为将一个左值转成右值将亡值,然后将所有权转给另一个对象。

    1. int main() {
    2. // 创建一个vector对象v1,包含一些整数
    3. std::vector<int> v1 = {1, 2, 3, 4, 5};
    4. // 使用std::move将v1的所有权转移给v2
    5. std::vector<int> v2 = std::move(v1);
    6. return 0;
    7. }

    8、完美转发

    右值引用和左值引用本身是左值还是右值? 

    1. int a= 10;
    2. int &r = a;
    3. int &&rr = 10;

    r和rr都是左值,否则如果右值引用的属性不是左值的话,下面的场景就无法实现:

    s本身是左值,才有可能传给swap(string& s)

    万能引用

    1. template<typename T>
    2. void PerfectForward(T && t){
    3. Fun(t);
    4. }

    T&&:这是万能引用,既可以接收左值,也可以接收右值。

    如果实参是左值,他就是左值引用(引用折叠)

    如果实参是右值,他就是右值引用 

    注意:因为左值和右值引用本身一定是左值,所以t本身一定是左值。所以最后无论传的实参是左值还是右值,调用的都是左值引用。

    如何让t保持T它原本的属性? 完美转发

    1. template<typename T>
    2. void PerfectForward(T && t){
    3. Fun(forward(t));
    4. }

  • 相关阅读:
    重学操作系统(二)进程管理
    【webrtc】Migrating your native/mobile application to Unified Plan/WebRTC 1.0 API.
    微服务如何改变软件开发:实战经验与最佳实践分享
    嵌入式系统工程师错题总结
    PCL 坡度滤波算法地面分割(C++详细过程版)
    一文读懂什么是 OCR 识别
    Linux内核学习①:内核的下载、编译及过程中的问题处理
    中小企业数字化思考:数字化转型应该走自己的路
    工业智能化转型升级难?华为云这三招,加速商业变现
    基于STC15系列库操作LED灯
  • 原文地址:https://blog.csdn.net/m0_73065213/article/details/138167037