关于右值引用

C++编程语言中有左值和右值的概念,左值可出现在赋值运算符=的左边,有名称且可寻址,而右值不能出现在=左边,通常无名称。右值引用是一种特殊的引用类型,用于绑定到右值,有助于优化,比如移动语义。右值引用不能直接绑定到非const的左值引用,但可以通过const左值引用或自身是右值引用的方式初始化。

 什么是右值?

在c++中有左值和右值的概念。通常来说,能够出现在 ”=“ 左边的,有名称的,可以寻址的我们称之为左值,不能出现在 ”=“ 左边的,没有名称的值我们称之为右值。

举几个栗子:

int a=5;  //a是一个int型变量,是左值
           //5是一个右值
char *c="hello world";  //c是一个左值, ”hello world“是一个右值

int func()   //非引用的返回值都是右值
{
    return 0;
}

什么是右值引用?

c++中存在引用,我们平常敲代码时可能用的比较多的引用就是形如下面这种:

int a=5;
int &b=a;   //定义一个a的引用(需要注意的是,引用必须在定义时初始化)

因为a是一个左值,所以这种引用也被称为左值引用,b即是a的一个别名。右值引用即如下所示:

int && a=5;  //右值引用

值得注意的是,我们无法用一个右值来初始化左值引用,除非是通过 const修饰 的常量左值引用:

int func()
{
    return 0;
}

int main(){
    int &a = 5;  //用右值初始化左值引用,编译不通过
    int &b = func();  //同上
    const int &c=5;  //编译通过
    const int &d=func();  //编译通过
    int && e=func();   //编译通过
}

### 引用引用的概念及区别 #### 概念定义 在 C++ 中, (lvalue) 和 (rvalue) 是表达式的两种基本分类。 - ****是指具有持久地址的表达式,通常表示对象本身,可以出现在赋运算符侧。例如变量名 `a` 或数组元素 `arr[i]` 都是[^1]。 - ****则是指临时对象或者不具持久地址的表达式,无法作为赋目标。例如字面量 `42` 或函数返回的结果都是。 #### 引用类型的区别 C++ 提供了两种类型引用引用 (`T&`) 和引用 (`T&&`)。它们的主要区别在于绑定的对象类型不同: - **引用 (`T&`)**:只能绑定,用于扩展对象生命周期并允许修改原对象的内容。它广泛应用于函数参数传递以及拷贝构造函数中[^2]。 ```cpp int x = 5; int& ref_x = x; // 绑定 'x' ``` - **引用 (`T&&`)**:专门设计用来捕获即将销毁的对象(即),从而实现资源转移而复制操作,这是现代 C++ 移动语义的核心机制之一[^1]。 ```cpp std::string str("hello"); std::string&& rref_str = std::move(str); // 绑定 'str' 的移动版本 ``` #### 使用场景分析 | 类型 | 常见用途 | |-----------------|----------------------------------------------------------------------------------------------| | **常量引用 (`T&`)** | 主要用于需要改变原始数据的情况;也常见于函数参数列表里当希望按引用方式处理输入时 | | **常量引用 (`const T&`)** | 当不想更改源数据又想避免不必要的拷贝开销时使用,比如大对象作为只读参数传入方法体内 | | **常量引用 (`T&&`)** | 实现高效的数据传输通过标准库容器或自定义类支持 move 构造/assign 功能 | | **常量引用 (`const T&&`)** | 虽然语法上合法但实际上很少单独出现因为其功能可由其他形式替代如 const lvalue reference | 具体来说, 对于恒定性的参照(`T&&`)而言, 它们主要服务于两个目的:一是配合模板元编程达成所谓"完美转送"(perfect forwarding),二是启用所谓的"移动建构子"/"移动分配者",借此减少深层副本创建所带来的效能损失. ```cpp // 示例代码展示如何利用引用来优化性能 #include <iostream> #include <utility> using namespace std; struct LargeObject { char data[1024]; // 占用大量内存空间 // Copy constructor LargeObject(const LargeObject&) { cout << "Copy Constructor called." << endl; } // Move constructor LargeObject(LargeObject&& other) noexcept : data{} { memcpy(data, other.data, sizeof(data)); memset(other.data, 0, sizeof(other.data)); // 清除旧对象中的内容 cout << "Move Constructor called." << endl; } }; LargeObject createObj(){ return LargeObject(); // 返回一个临时对象(纯) } int main(){ auto obj1 = createObj(); // 调用了移动构造函数而不是拷贝构造函数 } ``` 以上例子清晰表明,在适当条件下运用引用能够显著提升程序运行效率,尤其是在涉及频繁创建与销毁大型结构体实例的情形下尤为明显。 ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值