Skip to main content
 首页 » 编程设计

C++中的ravalue学习笔记

2022年07月19日27lvdongjie

一、学习笔记

1. A a = 42; 会先以42为参数构造一个A类对象,然后调用拷贝构造函数来构造a,目前编译器优化掉了拷贝构造函数的调用,测试拷贝构造函
数是没有被调用的,但是其权限不能为private的,即使提供了重载的拷贝构造函数(其它没有调用到的构造函数可以被设置为private的)

2. 打印出下面两个地址相同,编译器优化过了

B get() { 
    B b1(1); 
    cout << &b1 << endl; //地址1 
    return b1; 
} 
 
int main() { 
    B b = get(); 
    cout << &b << endl; //地址2 
    return 0; 
}

3. C++11标准引入了右值引用,使用它可以使临时对象的拷贝具有move语意,从而可以使临时对象的拷贝具有浅拷贝般的效率,这样便可以从
一定程度上解决临时对象的深度拷贝所带来的效率折损。

4. 区分一个表达式是左值还是右值,最简便的方法就是看能不能够对它取地址:如果能,就是左值;否则,就是右值。
由于右值引用的引入,C++11标准中对表达式的分类不再是“非左即右”那么简单,不过为了简单地理解,我们暂时只需区分左值右值即可,C++11标准中的分类后面会有描述。

5. 下面简单地总结了左值引用和右值引用的绑定规则(函数类型对象会有所例外):
(1)非const左值引用只能绑定到非const左值;
(2)const左值引用可绑定到const左值、非const左值、const右值、非const右值;
(3)非const右值引用只能绑定到非const右值;
(4)const右值引用可绑定到const右值和非const右值。

6. 右值引用绑定到字面值常量同样符合上述规则,例如:int &&rr = 123;,这里的字面值123虽然被称为常量,可它的类型为int,而不是const int。对此C++03标准文档4.4.1节及其脚注中有如下说明:

7. 模板参数的推导其实就是形参和实参的比较和匹配,如果形参是一个引用类型(如P&),那么就使用P来做类型推导;如果形参是一个cv-unqualified(没有const和volatile修饰的)右值引用类型(如P&&),并且实参是一个左值(如类型A的对象),就是用A&来做类型推导(使用A&代替A)。

二、Demo

struct A { 
    A(){}  
}; 
 
A rvalue() {return A();}              // 返回一个非const右值对象 
const A const_rvalue() {return A();}  // 返回一个const右值对象 
 
// void fun() {} 
// typedef decltype(fun) FUN;  // typedef void FUN(); 
 
int main() 
{ 
 
    A lvalue;                             // 非const左值对象 
    const A const_lvalue;                 // const左值对象 
 
 
    // 规则一:非const左值引用只能绑定到非const左值 
    A &lvalue_reference1 = lvalue;         // ok 
    A &lvalue_reference2 = const_lvalue;   // error 
    A &lvalue_reference3 = rvalue();       // error 
    A &lvalue_reference4 = const_rvalue(); // error 
 
    // 规则二:const左值引用可绑定到const左值、非const左值、const右值、非const右值 
    const A &const_lvalue_reference1 = lvalue;         // ok 
    const A &const_lvalue_reference2 = const_lvalue;   // ok 
    const A &const_lvalue_reference3 = rvalue();       // ok 
    const A &const_lvalue_reference4 = const_rvalue(); // ok 
 
    // 规则三:非const右值引用只能绑定到非const右值 
    //A &&rvalue_reference1 = lvalue;         // error 
    //A &&rvalue_reference2 = const_lvalue;   // error 
    //A &&rvalue_reference3 = rvalue();       // ok 
    //A &&rvalue_reference4 = const_rvalue(); // error 
 
    // 规则四:const右值引用可绑定到const右值和非const右值,不能绑定到左值 
    //const A &&const_rvalue_reference1 = lvalue;         // error 
    //const A &&const_rvalue_reference2 = const_lvalue;   // error 
    //const A &&const_rvalue_reference3 = rvalue();       // ok 
    //const A &&const_rvalue_reference4 = const_rvalue(); // ok 
 
    // 规则五:函数类型例外 
    //FUN       &  lvalue_reference_to_fun       = fun; // ok 
    //const FUN &  const_lvalue_reference_to_fun = fun; // ok 
    //FUN       && rvalue_reference_to_fun       = fun; // ok 
    //const FUN && const_rvalue_reference_to_fun = fun; // ok 
 
    return 0; 
}

参考:https://www.cnblogs.com/opangle/archive/2012/11/19/2777131.html


本文参考链接:https://www.cnblogs.com/hellokitty2/p/10632191.html