网站建设公司利润怎么样,中国建筑业未来发展展望,wordpress 模板修改,国外免费logo网站文章目录 1. 统一的列表初始化{ } 初始化initializer_list 2. 引用左值引用右值引用左值引用与右值引用的相互转换右值引用的真正使用场景移动构造 C98与C11传值返回问题注意事项总结 3. 完美转发 1. 统一的列表初始化
{ } 初始化
C11 扩大了括号括起的列表(初始化列表)的使用… 文章目录 1. 统一的列表初始化{ } 初始化initializer_list 2. 引用左值引用右值引用左值引用与右值引用的相互转换右值引用的真正使用场景移动构造 C98与C11传值返回问题注意事项总结 3. 完美转发 1. 统一的列表初始化
{ } 初始化
C11 扩大了括号括起的列表(初始化列表)的使用范围使其可用于所有的内置类型和用户自定义类型 使用初始化列表可添加等号()也可不添加 将1赋值给x1x2处省略了赋值符号将5赋值给x2 同样也可以将new开辟4个int的空间初始化为0 创建对象时可以使用列表初始化方式调用构造函数初始化也可省略等号
initializer_list 花括号里面的常量数组C可以将其识别成一个类型 initializer_list initializer_list这个类带有模板参数因为传过来的int数据所以为 initializer_list 类中存在两个指针 size作为两个指针相减 begin指向开始的位置end 指向结束位置的下一个 对数据不能修改说明指向的内容在常量区 任意的常量数组 都可以赋值给 initializer_list的对象 C11中 的vector是 通过新增的构造函数的方式 使用 initializer_list 进行初始化
2. 引用
左值引用
左值引用就是给左值取别名 左值是一个数据的表达式(如变量名或者引用指针) 可以获取它的地址 即为左值 左值出现赋值符号的左边 (也可出现在右边) 右值引用 右值也是一个表示数据的表达式(如字面常量、表达式返回值、函数返回值) 右值可以出现在赋值符号的右边但不能出现赋值符号的左边右值不能取地址
右值引用 就是 给右值起别名 左值引用与右值引用的相互转换 xy 作为右值 左值引用是无法直接引用右值的 但可以通过隐式类型转换的方式由于 临时变量具有常性 加入 const 即可 a作为左值 右值引用是无法直接引用左值 使用move 后其返回值作为右值
右值引用的真正使用场景 虽然可以在左值中加入const 既可以使用左值 又可以使用右值 但是 无法区分到底是左值还是右值的 加入右值引用后传参过程中更好的进行参数匹配 就可以 区分 是调用 左值引用 还是 右值引用 移动构造
右值分为两种 1.纯右值(内置类型) 2.将亡值(自定义类型) s1作为左值调用拷贝构造 s1s2 作为表达式返回值代表右值 即 将亡值 若右值进行深拷贝(再创建一块空间在原有的数据拷贝过来然后释放原有空间) 将亡值 是没有必要拷贝代价太大了 由于有const所以无论是左值还是右值都可以传过来作为参数 将右值(将亡值) 的资源进行转移ret2 使用右值引用 区分出右值后就没有必要进行深拷贝了 接收右值 作为参数 的拷贝 称为 移动拷贝 调用移动构造进行移动拷贝 右值就不再调用深拷贝而是使用移动拷贝
C98与C11传值返回问题 对于传值返回C98 刚开始会进行两次拷贝构造 编译器优化后会进行一次拷贝构造 编译器不优化时 str作为临时变量 属于左值 将str传给 临时变量 属于拷贝构造 临时对象 是看不见摸不着的 无法知道它的地址 所以属于 右值 (将亡值 所以将右值传给 str 属于 移动构造
编译器优化时 编译器会想办法将 函数中的临时变量 str 识别成 右值(使用move其函数返回值为右值)进行移动构造 (资源转移) s2 进行深拷贝 将s1的数据拷贝到新开辟的空间中 move(s1)后表达式返回值作为右值 s3 进行移动拷贝把s1的资源转移到s3中所以导致s1为空
注意事项 右值是不可以取地址的但是给右值取别名后会导致右值存储到特定位置并且可以取到该位置地址 如不能取到字面常量10的地址但是ret引用后可以对ret取地址也可以修改ret如果像ret不能修改需要加入const 即 const int
总结
左值引用减少拷贝提高效率 右值引用也是减少拷贝提高效率 但角度不同 左值引用是直接减少拷贝 右值引用是间接减少拷贝识别出是左值还是右值若识别出是右值则不再深拷贝 直接移动拷贝(资源转移)提高效率
3. 完美转发 写一个函数 无论传过来的参数为左值还是右值都可以接受 (将左值move后返回值为右值)
当左值作为参数 时 会发生引用折叠调用 fun(t)此时t作为左值所以会输出 左值引用 当右值作为参数时实际上右值接收后要进行移动拷贝右值引用 引用后属性会变成左值否则无法进行资源转移 调用push_back 参数为右值右值引用 引用后属性会变成左值但是 变为左值为了进行 资源转移的 还没等进行转移 在这期间先调用 insert (x作为左值)调用左值引用的insert 就会导致 进行深拷贝而不是进行移动拷贝 C支持 完美转发 用于保持原有的属性避免 参数x在资源转移之前 转过早的情况 所以当此时fun 参数 加入forward 完美转发后使右值 引用后并没有立即变为左值而是保持原有的属性 右值 所以 调用 对应的fun 打印 右值引用