左值与右值

C++11标准之右值引用(ravalue reference)

白昼怎懂夜的黑 提交于 2020-03-28 02:57:00
1、右值引用引入的背景 临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题。但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了Copy Elision、RVO(包括NRVO)等编译器优化技术,它们可以防止某些情况下临时对象产生和拷贝。下面简单地介绍一下Copy Elision、RVO,对此不感兴趣的可以直接跳过: (1) Copy Elision Copy Elision技术是为了防止某些不必要的临时对象产生和拷贝,例如: struct A { A(int) {} A(const A &) {} }; A a = 42; 理论上讲,上述A a = 42;语句将分三步操作:第一步由42构造一个A类型的临时对象,第二步以临时对象为参数拷贝构造a,第三步析构临时对象。如果A是一个很大的类,那么它的临时对象的构造和析构将造成很大的内存开销。我们只需要一个对象a,为什么不直接以42为参数直接构造a呢?Copy Elision技术正是做了这一优化。 【说明】:你可以在A的拷贝构造函数中加一打印语句,看有没有调用,如果没有被调用,那么恭喜你,你的编译器支持Copy Elision。但是需要说明的是:A的拷贝构造函数虽然没有被调用,但是它的实现不能没有访问权限,不信你将它放在private权限里试试,编译器肯定会报错。 (2) 返回值优化(RVO,Return

左值引用与右值引用

久未见 提交于 2020-03-26 09:44:50
转自: https://www.cnblogs.com/simplepaul/p/7788009.html 1、左值和右值的概念 左值是可以放在赋值号左边可以被赋值的值; 左值必须要在内存中有实体 ; 右值当在赋值号右边取出值赋给其他变量的值; 右值可以在内存也可以在CPU寄存器 。 一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。 2、引用 引用是C++语法做的优化,引用的 本质还是靠指针 来实现的。 引用相当于变量的别名 。 引用可以改变指针的指向,还可以改变指针所指向的值。 引用的基本规则: 声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象;即引用 必须初始化 , 不能对引用重定义; 对引用的一切操作,就相当于对原对象的操作。 3、左值引用和右值引用 3.1 左值引用 左值引用的基本语法:type &引用名 = 左值表达式; 3.2 右值引用 右值引用的基本语法type &&引用名 = 右值表达式; 右值引用在企业开发人员在代码优化方面会经常用到。 右值引用的“&&”中间不可以有空格。 来源: https://www.cnblogs.com/xuhongfei0021/p/12572136.html

C语言数据类型转换

房东的猫 提交于 2020-03-15 18:04:11
目录 一、自动类型转换 1、操作数中没有浮点型数据时 2、操作数中有浮点型数据时 3、赋值运算符两侧的类型不一致时 4、右值超出左值类型范围时 二、强制类型转换 三、课后作业 四、版权声明 计算机进行算术运算时,要求各操作数的类型具有相同的大小(存储位数)及存储方式,不能将char 型( 1 字节)数据与 int 型(2、4或8字节)数据直接参与运算;由于存储方式的不同,也不能将 int 型数据与 double 型数据直接参与运算。 然而,由于 C语言的灵活性,在一个表达式或一条语句中,允许不同类型的数据混合运算。 C语言的灵活性与计算机的机械性是一对矛盾,如处理不好,将会产生错误结果。对于某些类型的转换编译器可隐式地自动进行,不需程序员干预,称这种转换为 自动类型转换 ;而有些类型转换需要程序员显式指定,这种类型转换称为 强制类型转换 。 一、自动类型转换 一个表达式中出现不同类型间的混合运算,较低类型将自动向较高类型转换。 不同数据类型之间的差别在于数据的取值范围和精度上,一般情况下,数据的取值范围越大、精度越高,其类型也越“高级”。 整型类型级别从低到高依次为: signed char->unsigned char->short->unsigned short->int->unsigned int->long->unsigned long 浮点型级别从低到高依次为:

左值与左值引用、右值与右值引用、移动构造函数。

爷,独闯天下 提交于 2020-03-11 12:19:25
1、什么是左值:可以被引用取地址的值。 const int a = 12 ; // a为左值 const int & pt = a ; // pt为左值引用 double x1 = 1.2 ; // x1为左值 double & x2 = x1 ; // x2为左值引用 c风格字符串为左值。 详细介绍:C++ Primer Plus 8.2.3 2、什么是右值:可以出现在赋值表达式右边,但不能对其应用地址运算符的值。 int a = 10 ; int b = 12 ; int && x1 = 13 ; // 13为右值 int && x2 = a + b ; //a+b为右值 double && x3 = std :: sqrt ( 2.0 ) //std::sqrt(2.0)函数返回值为右值 double * ptr = & x1 ; // 通过右值引用获得13存储的地址 引入右值引用的目的之一:实现移动语义。 详细介绍:C++ Primer Plus 18.1.9 3、移动语义 不删除原对象,将其数据保留在原来位置,将现有对象与该位置关联。类似计算机中移动文件(只是移动了索引路径)。 4、移动构造函数与移动赋值运算符 例子: //.h Class Useless { public : Useless ( Useless && f ) ; // 移动构造函数,非const

十二、 C++特性之 杂合

一笑奈何 提交于 2020-03-06 23:50:02
static_assert和 type traits static_assert提供一个编译时的断言检查。如果断言为真,什么也不会发生。如果断言为假,编译器会打印一个特殊的错误信息。 template < typename T, size_t Size> class Vector { static_assert(Size < 3, "Size is too small"); T _points[Size]; }; int main() { Vector< int, 16> a1; Vector< double, 2> a2; return 0; } error C2338: Size is too small see reference to class template instantiation 'Vector<T,Size>' being compiled with [ T= double, Size=2 ] static_assert和type traits一起使用能发挥更大的威力。type traits是一些class,在编译时提供关于类型的信息。在头文件<type_traits>中可以找到它们。这个头文件中有好几种 class: helper class,用来产生编译时常量。type traits class,用来在编译时获取类型信息,还有就是type

使用前进的优势

南笙酒味 提交于 2020-02-27 20:07:17
在理想的转发中, std::forward 用于将命名的右值引用 t1 和 t2 转换为未命名的右值引用。 这样做的目的是什么? 如果将 t1 和 t2 保留为左值,这将如何影响被调用函数的 inner ? template <typename T1, typename T2> void outer(T1&& t1, T2&& t2) { inner(std::forward<T1>(t1), std::forward<T2>(t2)); } #1楼 我认为有一个实现std :: forward的概念代码可以增加讨论的范围。 这是斯科特·迈耶斯(Scott Meyers)讲 的《有效的C ++ 11/14采样器》中的 一张幻灯片 代码中的函数 move 为 std::move 。 在该演讲的前面有一个(有效的)实现。 我 在libstdc ++ 中的move.h文件中找到 了std :: forward的实际实现 ,但这根本没有启发性。 从用户的角度来看,其含义是 std::forward 是有条件强制转换为右值。 如果我编写的函数期望参数中包含左值或右值,并且仅当将其作为右值传递时,希望将其作为右值传递给另一个函数,则该功能很有用。 如果我没有将参数包装在std :: forward中,它将始终作为常规引用传递。 #include <iostream> #include

C++ 右值引用

蓝咒 提交于 2020-02-24 14:19:55
左值和右值 左值:当一个对象被用作左值的时候,用的是对象的身份(在内存中的位置)。 右值:当一个对象被用作右值的时候,用的是对象的值(内容)。 右值引用 重要性质:右值引用只能绑定到一个将要销毁的对象。因此,我们可以自由的将一个右值引用的资源移动到另一个对象中。 标准库move函数 move函数定义在头文件utility中,通过调用move函数可以获得绑定到左值上的右值引用。 int &&rr3 = std::move(rr1); move调用告诉编译器:我们有一个右值,但我们希望像一个右值一样处理它。意味着,除了对rr1赋值或销毁它外,我们将不再使用它的值。 注意:使用move应该使用std::move而不是move。这样可以避免潜在的名字冲突。 移动构造函数 类似拷贝构造函数,移动构造函数的第一个参数是该类类型的一个引用。不同于拷贝构造函数的是,这个引用参数在移动构造函数中是一个右值引用。与拷贝构造函数一样,任何额外的参数都必须有默认实参。 与拷贝构造函数不同,移动构造函数不分配任何新内存;它接管给定的对象中的内存。在接管内存之后,它将给定对象中的指针都置为nullptr。这样就完成了从给定对象的移动操作,此对象将继续存在。 移动赋值运算符 来源: https://www.cnblogs.com/xiaobaizzz/p/12356541.html

C@指针&数组

拟墨画扇 提交于 2020-02-15 00:54:03
一、指针数组和数组指针 1、字面意思理解指针数组和数组指针 指针数组的实质就是一个数组,这个数组中存储的内容全部是指针变量 数组指针的实质是一个指针,这个指针指向的是一个数组。 2、分析指针数组和数组指针的表达式 (1)int*p[5]; int(*p)[5]; int *(p[5]); (2)一般规律 :int *p;(p是一个指针) int p[5] ;(p是一个数组) 总结:我们定义一个符号时,关键在于首先找到定义的符号是谁(第一步找核心) 其次再来看谁跟核心最近,谁跟核心结合(第二部:找结合) 以后继续向外扩展(第三步:继续向外结合直到符号完) (3)核心结合 - 如何核心和 “ * ”结合,表示核心是指针, - 如果核心和“[ ]”结合表示核心是数组, - 如果核心和小括号“()”结合,表示核心是函数 (4)一般规律来分析3个符号 例子1: int *p[5]; (“[ ]”的优先级比“ * ”优先级高) p是一个数组,数组有5个元素,数组中的元素都是指针,指针指向的元素类型是int类型,整个符号是一个指针数组。 例子2: int (*p)[5]; 核心是p,p是一个指针,因为p被用括号和星好强制结合起来了。指针指向一个数组,数组有5个元素,数组中存在的元素是int类型; 例子3: int *(p[5]); 这里 加小括号没有意义,没起到左右,没有小括号,也是p与[

c++11 右值引用、移动语义和完美转发

て烟熏妆下的殇ゞ 提交于 2020-02-14 03:19:49
c++11 右值引用、移动语义和完美转发 作者:StormZhu 链接:https://www.jianshu.com/p/d19fc8447eaa c++中引入了 右值引用 和 移动语义 ,可以避免无谓的复制,提高程序性能。有点难理解,于是花时间整理一下自己的理解。 左值、右值 C++ 中所有的值都必然属于左值、右值二者之一。左值是指表达式结束后依然存在的 持久化对象 ,右值是指表达式结束时就不再存在的 临时对象 。所有的具名变量或者对象都是左值,而右值不具名。很难得到左值和右值的真正定义,但是有一个可以区分左值和右值的便捷方法: 看能不能对表达式取地址,如果能,则为左值,否则为右值 。 看见书上又将右值分为将亡值和纯右值。纯右值就是 c++98 标准中右值的概念,如非引用返回的函数返回的临时变量值;一些运算表达式,如1+2产生的临时变量;不跟对象关联的字面量值,如2,'c',true,"hello";这些值都不能够被取地址。 而将亡值则是 c++11 新增的和右值引用相关的表达式,这样的表达式通常时将要移动的对象、 T&& 函数返回值、 std::move() 函数的返回值等, 不懂将亡值和纯右值的区别其实没关系,统一看作右值即可,不影响使用。 示例: int i=0;// i是左值, 0是右值 class A { public: int a; }; A getTemp() {

[转][c++11]我理解的右值引用、移动语义和完美转发

自作多情 提交于 2020-02-13 22:25:42
c++中引入了 右值引用 和 移动语义 ,可以避免无谓的复制,提高程序性能。有点难理解,于是花时间整理一下自己的理解。 左值、右值 C++ 中所有的值都必然属于左值、右值二者之一。左值是指表达式结束后依然存在的 持久化对象 ,右值是指表达式结束时就不再存在的 临时对象 。所有的具名变量或者对象都是左值,而右值不具名。很难得到左值和右值的真正定义,但是有一个可以区分左值和右值的便捷方法: 看能不能对表达式取地址,如果能,则为左值,否则为右值 。 看见书上又将右值分为将亡值和纯右值。纯右值就是 c++98 标准中右值的概念,如非引用返回的函数返回的临时变量值;一些运算表达式,如1+2产生的临时变量;不跟对象关联的字面量值,如2,'c',true,"hello";这些值都不能够被取地址。 而将亡值则是 c++11 新增的和右值引用相关的表达式,这样的表达式通常时将要移动的对象、 T&& 函数返回值、 std::move() 函数的返回值等, 不懂将亡值和纯右值的区别其实没关系,统一看作右值即可,不影响使用。 示例: int i=0;// i是左值, 0是右值 class A { public: int a; }; A getTemp() { return A(); } A a = getTemp(); // a是左值 getTemp()的返回值是右值(临时变量)   左值引用、右值引用