首页
学习
活动
专区
圈层
工具
发布

终于弄明白了万能引用和右值引用的区别

1,这个右值无法传递给 std::string得移动构造函数,因为移动构造函数只能接受非常量 std::string型别得右值引用作为形参 2,这个右值可以传递给复制构造函数,因为指涉到常量得左值引用允许绑定到一个常量右值型别得形参...两种含义: 1, 右值引用,仅仅会绑定到右值,识别出可移动对象 2,万能引用,可以是左值引用 T&,也可以是右值引用, 也可以绑定到 const对象或 volatile对象或非两者对象 */ //右值引用...//万能引用:首先是个引用,初始化是必需的,万能引用的初始化物会决定它代表的是个左值还是右值引用 //1,如果初始化是右值,万能引用就会对应到一个右值引用 //2,如果初始化物是左值,万能引用就会对应到一个左值引用...如下是错误的,一个右值引用不能绑定一个左值 std::vector v; f(v); //2 //const修饰,也不是万能引用 //2 //const修饰,也不是万能引用 template...p 被初始化,模板构造函数可以实例化来接受 Person型别的非常量左值形参 */ const Person cp("nacy"); Person cpp(cp); } 条款

2.1K10

【笔记】《C++Primer》—— 第三部分:类设计者的工具

我们可以认为右值引用的目标对象都是将要被销毁且没有其他用户的,也就是可以自由使用其引用对象,正是这个特性让我们可以移动那些不可拷贝的值 右值引用有与左值引用完全相反的特性,我们无法将右值引用绑定到左值上...但我们可以将const左值引用绑定到右值上 移动构造的具体写法类似拷贝构造,但是构造参数是自己类型的右值引用,为了完成移动构造,我们需要保证移动后源对象处于可以无害销毁的状态,源对象的指针不再指向原先的资源...,参数是左值使用拷贝,参数是右值或不可拷贝使用移动 为了达成易用性与性能间的平衡,当我们定义自己的函数时,可以对其重载一个constX&参数的左值引用形式和X&&的右值引用形式 引用限定符也可以用来区分重载...,非类型参数表示的是一个值而不是类型,因此非类型参数在编译时会被用户提供或编译器推断的一个常量代替,从而允许我们初始化数组之类 非类型参数可以是整型或指向对象或函数的指针或左值引用,但是注意绑定到非类型整型必须是常量表达式...&&,也就是删去两个引用符 左值如i传递给模板类型的右值引用时,编译器会推断参数类型为左值引用i& 直接利用右值引用参数会丧失右值引用属性,这时我们可以通过让右值引用后进入函数的参数调用utility文件中的

2.1K10
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    《C++Primer》第十六章 模板与泛型编程

    是底层的,不是顶层的 5.1 从左值引用函数参数推断类型 当一个函数参数是模板类型参数的一个普通(左值)引用时(即形如T&),绑定规则告诉我们只能给它一个左值(比如一个变量或者一个返回引用类型的表达式)...毕竟i是一个左值,而通常我们不能将一个右值引用绑定到一个左值上。...但是C++在正常绑定规则外定义了两个例外规则,允许这种绑定: 第一个例外规则:当我们将一个左值(如i)传递给函数的右值引用参数,且此右值引用指向模板类型参数(如T&&)时,编译器推断模板类型参数为实参的左值引用类型...使用右值引用的函数模板通常要进行重载: // 右值会调用第一个函数, 排除歧义的问题 template void f(T&&); // 绑定到非const右值 template...理解std::move 虽然不能直接将一个右值引用绑定到一个左值上,但可以用move获得一个绑定到左值上的右值引用。

    2.2K10

    左值和右值、左值引用与右值引用、移动语句(2)「建议收藏」

    左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。 左值引用通常也不能绑定到右值,但常量左值引用是个“万能”的引用类型。它可以接受非常量左值、常量左值、右值对其进行初始化。...,不能绑定到常量左值、非常量右值和常量右值。...非常量右值引用只能绑定到非常量右值,不能绑定到非常量左值、常量左值和常量右值。...常量右值引用可以绑定到非常量右值和常量右值,不能绑定到非常量左值和常量左值(理由同上)。 有了右值引用的概念,我们就可以用它来实现下面的CMyString类。...当添加了move版本的构造函数和赋值函数的重载形式后,某一个函数调用应当使用哪一个重载版本呢?下面是按照判决的优先级列出的3条规则: 1、常量值只能绑定到常量引用上,不能绑定到非常量引用上。

    2.9K20

    C++ 左值和右值

    左值和右值 在C++11之前,一个变量分为左值和右值:左值是可以放在=运算符左边的值,有名字,可以用&运算符取地址(如 int n = 10;n即为左值);右值则是只能放在=运算符右边,没有名字,不能用...左值引用和右值引用都属于引用类型,都必须在声明时进行初始化,而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。...一般情况下,左值引用只能接受左值对其进行初始化,右值引用只能接受右值对其进行初始化;但常左值引用是个例外,它是“万能”的引用类型:它可以接受非常量左值、常量左值、右值对其进行初始化,不过只能通过引用来读取数据...只是左值引用绑定的对象一般为左值(常左值引用可以绑定到右值对象),而右值引用绑定的对象为右值。即引用类型对象本身的左右值属性与其绑定的对象的左右值属性无关。...对于自定义类型T的对象t:如果t为左值,那么t的非静态成员也为左值,如果t为右值,那么t的非静态成员也为右值。

    1.5K181

    C++11特性大杂烩

    initializer_list底层是一个常量数组,存放在常量区(不能随意修改),initializer_list就是对这个常量数组进行封装。...因为这个迭代器类型由一个类模板来定义,在该类模板未被实例化之前编译器是无法识别这个类型最好也增加一个用initializer_list为参数的赋值运算符重载函数,来支持对列表对象进行赋值。...右值有以下特性右值是一个表示数据的表达式(这点跟左值没差阿),比如:字面常量,表达式返回值,函数返回值、临时变量、匿名对象等等右值不能出现在赋值符号的左边,但可以出现在赋值符号的右边左值引用能引用左值,不能引用右值;const左值引用能引用右值;(通俗理解:一些情况下右值不能被修改,const左值引用不能修改参数,性质符合这一点;其次是右值被const左值引用,权限被平移或者缩小了...)右值引用能引用右值,不能引用左值右值引用能引用move之后的左值(move

    1.1K50

    C++运算符重载详解

    除运算符外其他运算符都是二元运算符,而且运算的结果和原来的值无关,并且不能做左值引用。...} }; 从上面的例子可以看出: 函数的返回都是普通类型而不是引用类型是因为这些运算符计算出来的结果都和输入的数据并不是相同的对象而是一个临时对象,因此不能返回引用类型,也就是不能再作为左值使用。...,因此左边参数不能是常量而只能是引用类型。...前缀自增的返回是引用类型可以做左值,而后缀自增的返回类型则是值类型不能做左值。 参数中有int声明的是前缀自增而没有int声明的是后缀自增。...6.赋值运算符 描述 值 运算符种类 = 是否支持类成员 YES 是否支持普通函数 NO 运算单元 二元 返回类型 左值引用 赋值运算符只能用于类的成员函数中不能用于普通函数。

    1.7K30

    【Modern C++】深入理解左值、右值

    C++11之前,左值遵循了C语言的分类法,但与C不同的是,其将非左值表达式统称为右值,函数为左值,并添加了引用能绑定到左值但唯有const的引用能绑定到右值的规则。...左值具有以下特征: 可通过取地址运算符获取其地址 可修改的左值可用作内建赋值和内建符合赋值运算符的左操作数 可以用来初始化左值引用(后面有讲) 那么哪些都是左值呢?...rvalue不能放在赋值或者组合赋值符号的左边,例如:3 = 5,3 += 5,这些表达式没有意义,也编译不过。 rvalue可以用来初始化const左值引用(见下文)。...rvalue可以影响函数重载:当被用作函数实参且该函数有两种重载可用,其中之一接受右值引用的形参而另一个接受 const 的左值引用的形参时,右值将被绑定到右值引用的重载之上。...为了能区分左值引用和右值引用,代码如下: int a = 1; int &rb = a; // b为左值引用 int &&rrb = a; // 错误,a是左值,右值引用不能绑定左值 int &&rrb1

    1.2K21

    【笔记】《C++Primer》—— 第16章:模板与泛型编程

    ,非类型参数表示的是一个值而不是类型,因此非类型参数在编译时会被用户提供或编译器推断的一个常量代替,从而允许我们初始化数组之类 非类型参数可以是整型或指向对象或函数的指针或左值引用,但是注意绑定到非类型整型必须是常量表达式...通常情况下我们不能将左值传递给右值引用参数,但是C++设置了两个重要的例外来允许这种传递: 左值如i传递给模板类型的右值引用时,编译器会推断参数类型为左值引用i& 如果我们通过类型别名或模板参数之类的方法间接定义了引用的引用...T的类型,左值则推断出左值引用t&,右值则是去掉右值引用的t // 按照推断出来的类型T实例化emove_reference::type // 得到去掉引用引用的类型...::type&&>(inp); } 在move中我们在返回正确的类型时进行了强制类型转换static_cast,这里要注意是有另一个特例,我们不能隐式将左值转为右值引用...然后再用得到的信息正确的参数传递给其他函数,这就是转发操作 16.3 重载与模板 函数模板可以被另一个模板或非模板函数重载,与平时一样名字相同的函数需要参数不同才能重载 但是对于函数模板来说,实参调用的函数会是重载版本中的哪一个需要按照以下规则来判断

    1.9K30

    C++11新特性学习笔记

    因此a是一个左值,(b + c)是一个右值。 相对于左值,右值表示字面常量、表达式、函数的非引用返回值等。...无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。...左值引用: int &a = 2; // 左值引用绑定到右值,编译失败, err int b = 2; // 非常量左值 const int &c = b; // 常量左值引用绑定到非常量左值...,编译通过, ok const int d = 2; // 常量左值 const int &e = c; // 常量左值引用绑定到常量左值,编译通过, ok const int &b = 2; // 常量左值引用绑定到右值...,编程通过, ok “const 类型 &”为 “万能”的引用类型,它可以接受非常量左值、常量左值、右值对其进行初始化; 右值引用,使用&&表示: int && r1 = 22; int x = 5;

    2.6K20

    第 13 章 拷贝控制

    返回左值引用的函数,连同赋值、下标、解引用和前置递增/递减运算符,都返回左值。左值表达式通常表示的是一个对象的身份,不能将其绑定到要求转换的表达式、字面常量和返回右值的表达式。...返回非引用类型的函数,连同算术、关系、位以及后置递增/递减运算符,都返回右值。右值表达式通常表示对象的值,不可以绑定到左值上。另外,一个 const的左值引用也可以绑定到这些对象上。...int i = 42; int &r = i; // 正确,r引用 i int &&rr = i; // 错误,不能将一个右值引用绑定到左值上 int &...因此,不能将一个右值引用直接绑定到一个变量上,即使这个变量是右值引用也不行。...const T&的左值引用和 T&&的右值引用可以用来重载函数的拷贝和移动版本。

    1.2K50

    C++11新特性学习笔记

    因此a是一个左值,(b + c)是一个右值。 相对于左值,右值表示字面常量、表达式、函数的非引用返回值等。...无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。...左值引用: int &a = 2; // 左值引用绑定到右值,编译失败, err int b = 2; // 非常量左值 const int &c = b; // 常量左值引用绑定到非常量左值...,编译通过, ok const int d = 2; // 常量左值 const int &e = c; // 常量左值引用绑定到常量左值,编译通过, ok const int &b = 2; // 常量左值引用绑定到右值...,编程通过, ok “const 类型 &”为 “万能”的引用类型,它可以接受非常量左值、常量左值、右值对其进行初始化; 右值引用,使用&&表示: int && r1 = 22; int x = 5;

    2.4K20

    C++:31---对象引用和赋值

    引用(reference)称之为“左值引用” 右值引用的使用方法 左值引用: 不能将其绑定到要求“转换的表达式、字面值常量、返回右值的表达式” 返回左值的函数,连同赋值、下标、解引用和前置递增/递减运算符...我们可以将一个左值引用绑定到这类表达式的结果上 右值引用: 则与左值引用相反,我们可以将一个右值引用到上面所述的表达式上,但是不能将一个右值引用直接绑定到一个左值上 返回非引用类型的函数,连同算术、关系...、右值短暂 左值一般是绑定到对象身上,因此左值是持久的 而右值要么绑定在字面值常量、要么绑定到表达式求值过程中创建的临时对象身上,因此: 右值引用所引用的对象将要被销毁 该对象没有其他用户 这两个特性意味着...函数 虽然不能将一个右值引用绑定到一个左值上,但是我们可以显式地将一个左值转换成对应的右值引用类型 move函数就是实现上面的功能,move函数用来获得绑定到左值上的右值引用 此函数定义在头文件化 依赖实参的类型,拷贝初始化: 要么使用拷贝构造函数——左值被拷贝 要么使用移动构造函数——右值被移动 因此,此处定义的赋值运算符就实现了拷贝赋值运算符和移动赋值运运算符的两种功能

    2K10

    四、从C语言到C++(四)

    C++中的引用是一个已存在变量的别名,它允许我们通过一个不同的名字来访问同一个变量的内存位置。引用在声明时必须被初始化,并且之后不能被重新绑定到另一个对象。...在C++中,引用在声明时必须被初始化,并且之后不能被重新绑定到另一个对象。而在C中,指针可以在任何时候被重新赋值,指向不同的内存地址。...// ... } 常量引用(Constant Reference): 常量引用用于确保不能通过引用来修改所引用的值。...常引用(Constant Reference) 常引用是对一个变量或对象的常量引用,即你不能通过这个引用修改其所引用的值。...定义 完美转发允许函数模板将其参数“完美”地转发给另一个函数,同时保持参数的原始类型和值类别(左值或右值)不变。 2. 关键点 右值引用和模板类型推导:完美转发通过使用右值引用和模板类型推导来实现。

    46610

    【c++11】右值引用和移动语义

    右值(rvalue) 定义: 右值是不能被持久访问的临时值,通常是表达式的结果或常量值。右值没有具体的内存地址,或者它的地址无法被直接访问。...右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址 特点: 通常表示临时对象,生命周期只存在于当前表达式中。 不能被赋值,也不能绑定到普通的左值引用。...可以出现在赋值号左边或右边 只能出现在赋值号的右边 引用绑定 可以绑定到左值引用(T&) 不能绑定到左值引用,但能绑定到右值引用(T&&) (1)赋值规则 左值引用总结: 左值引用只能引用左值...int&& r1 = 10; // error C2440: “初始化”: 无法从“int”转换为“int &&” // message : 无法将左值绑定到右值引用 int a = 10;...函数调用的解析: 编译器根据参数的具体类型和值类别,推导模板参数并选择对应的函数重载。

    35210

    左右值引用和移动语义

    : 拥有身份 (identity):可以确定表达式是否与另一表达式指代同一实体,例如通过比较它们所标识的对象或函数的(直接或间接获得的)地址; 可被移动:移动构造函数、移动赋值运算符或实现了移动语义的其他函数重载能够绑定于这个表达式...将亡值的产生与右值引用的产生而引起的,对于将亡值我们常用到的有: 返回类型是右值引用的函数调用或重载运算符的表达式(如std::move(x)) 转换为右值引用的转换函数的调用表达式(如static<int...它的形式如:T&,根据const属性可以分为两种: const左值引用 非const左值引用 例如: int a = 1; int& la = a;//la为a的左值引用(非const左值引用) la...= 2;//la为非const左值引用,可以修改它的值 const int& c_la = a;//c_la为a的左值引用(const左值引用) c_la = 2;//该语法错误,c_la为const...,从函数形参移动构造它的目标 A a2(std::move(a1));// 从亡值移动构造 } 2.3 移动赋值运算符 一个类 T 的移动赋值运算符是名为 operator=的非模板非静态成员函数

    1.1K40

    《逆袭进大厂》第三弹之C++提高篇79问79答

    ,下标运算符通常以所访问元素的引用作为返回值,同时最好定义下标运算符的常量版本和非常量版本; 7、 箭头运算符必须是类的成员,解引用通常也是类的成员;重载的箭头运算符必须返回类的指针; 129、当程序中有函数重载时...左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。 左值引用通常也不能绑定到右值,但常量左值引用是个“万能”的引用类型。它可以接受非常量左值、常量左值、右值对其进行初始化。...不过常量左值所引用的右值在它的“余生”中只能是只读的。相对地,非常量左值只能接受非常量左值对其进行初始化。...4) 右值值引用通常不能绑定到任何的左值,要想绑定一个左值到右值引用,通常需要std::move()将左值强制转换为右值。...int& c = 10; //错误,c是左值不能使用右值初始化 int&& d = 10; //正确,右值引用用右值初始化 int&& e = a; //错误,e是右值引用不能使用左值初始化

    2.9K30

    C++复习知识点(仅供参考)

    ⾮0值转换为true,0值转换为false 三⽬运算符 C语言返回变量的值      C++语言是返回变量本身 1,C语言中的三目运算符返回的是变量值,不能作为左值使用 2,C++中的三目运算符可直接返回变量本身...,因此可以出现在程序的任何地方(如果有一个是常量值,则不能作为左值使用) Const是常变量,const修饰的常量编译期间,就已经确定下来了,由编译器处理的,提供类型检查和作用域检查 宏定义由预处理器处理...返回值类型 operator重载的运算符(参数表){……} //operator是关键字,它与重载的运算符一起构成函数名。...2>无论私有或非私有,必须在类外初始化,用(::)来指明所属的类。 3>静态成员函数只能直接访问类中的静态成员。 4>非静态成员时,必须借助对象名或指向对象的指针。...3>使用:类模板名 对象名 (初始化参数表) 4>模板非类型参数:表示该参数名代表了一个常量。

    22710
    领券