深入理解 C++ 中的左值和右值

一、左值的特征和用途

  • 可寻址性:左值是可以通过取地址得到的表达式,具有持久性。
  • 持久性:左值的生命周期通常与包含它的作用域相同。
  • 修改性:左值可以用于修改变量的值,是可被赋值的对象。
int x = 42;  // x 是左值
int y = x;   // x 可以被赋值给 y

二、右值的特征和用途

  • 临时性:右值通常是临时生成的,其生命周期可能只在表达式结束时。
  • 表达式结果:右值可以是表达式的结果,也可以是字面量或临时对象。
  • 初始化:右值常用于初始化操作,将值传递给其他对象。
int getResult() { return 42; }

int y = getResult();  // getResult() 是右值

三、移动语义和右值引用

移动语义的背景

传统的复制操作可能涉及大量资源的复制,引入了移动语义来解决右值的所有权和性能问题。

右值引用的概念

  • 引入 && 表示右值引用,允许我们对右值进行引用操作。
  • 示例:T&& 表示对类型 T 的右值引用。
template <typename T>
void processRValue(T&& rvalueRef) {
    // 对右值进行操作
}

移动语义的实现

  • 移动构造函数和移动赋值运算符用于实现移动语义。
  • 通过 std::move 转换左值为右值引用,避免资源的不必要复制。
class Example {
public:
    // 移动构造函数
    Example(Example&& other) noexcept {
        // 执行资源的转移操作
    }

    // 移动赋值运算符
    Example& operator=(Example&& other) noexcept {
        // 执行资源的转移操作
        return *this;
    }
};

Example createExample() {
    Example temp;
    // 生成临时对象
    return temp;
}

Example obj = createExample();

完美转发

完美转发的需求

函数模板和泛型编程中,需要处理各种类型的左值和右值,引入完美转发来解决参数传递的问题。

std::forward 的作用
  • std::forward 用于在函数中进行完美转发,保持参数原有的左值或右值特性。
  • 示例:使用 std::forward 进行完美转发。
template <typename T>
void forwardFunction(T&& arg) {
    processRValue(std::forward<T>(arg));
}

右值优化和 RVO

右值优化的概念

编译器通过右值优化(RVO)来减少临时对象的创建,提高效率。

返回值优化(RVO)
  • 返回值优化是一种编译器在函数返回时避免不必要的临时对象创建的优化手段。
  • 示例:演示 RVO 的使用场景。
Example createExample() {
    Example temp;
    // 生成临时对象
    return temp;  // 可能会被 RVO 优化
}

四、研究左值右值的测试代码

#include <iostream>

#include <string>
#include <vector>

class Test {
public:
    Test() {
        std::cout << "Test" << std::endl;
    }

    //析构函数
    ~Test() {
        if (data_) {
            std::cout << "[" << data_ << "] ~Delete" << std::endl;
            delete data_;
            data_ = nullptr;
        }
    }

    //左值函数
    Test( Test &other) noexcept {
        std::cout << "[" << other.data_ << "] Left copy" << std::endl;
        data_ = new char[4];
        memcpy(data_, other.data_, 4);
    }

    //右值函数
    Test(Test &&other) noexcept {
        std::cout << "[" << other.data_ << "] Right copy" << std::endl;
        data_ = other.data_;
        other.data_ = nullptr;
    }

public:
    char *data_{nullptr};
};
int main() {
    std::vector<Test> vec;
    for (uint32_t idx = 0; idx < 10; idx++) {
        std::cout << "------------------- start  --------------------" << std::endl;
        Test test;
        std::string data = std::to_string(idx);
        test.data_ = new char[12];
        std::strcpy(test.data_, data.c_str());
        vec.emplace_back(test);
        std::cout << "------------------- end  --------------------" << std::endl;
    }

    return 0;
}

运行结果:

C:\Users\CLionProjects\untitled\cmake-build-debug\untitled.exe
------------------- start  --------------------
Test
[0] Left copy
------------------- end  --------------------
[0] ~Delete
------------------- start  --------------------
Test
[1] Left copy
[0] Right copy
------------------- end  --------------------
[1] ~Delete
------------------- start  --------------------
Test
[2] Left copy
[0] Right copy
[1] Right copy
------------------- end  --------------------
[2] ~Delete
------------------- start  --------------------
Test
[3] Left copy
[0] Right copy
[1] Right copy
[2] Right copy
------------------- end  --------------------
[3] ~Delete
------------------- start  --------------------
Test
[4] Left copy
[0] Right copy
[1] Right copy
[2] Right copy
[3] Right copy
------------------- end  --------------------
[4] ~Delete
------------------- start  --------------------
Test
[5] Left copy
------------------- end  --------------------
[5] ~Delete
------------------- start  --------------------
Test
[6] Left copy
[0] Right copy
[1] Right copy
[2] Right copy
[3] Right copy
[4] Right copy
[5] Right copy
------------------- end  --------------------
[6] ~Delete
------------------- start  --------------------
Test
[7] Left copy
------------------- end  --------------------
[7] ~Delete
------------------- start  --------------------
Test
[8] Left copy
------------------- end  --------------------
[8] ~Delete
------------------- start  --------------------
Test
[9] Left copy
[0] Right copy
[1] Right copy
[2] Right copy
[3] Right copy
[4] Right copy
[5] Right copy
[6] Right copy
[7] Right copy
[8] Right copy
------------------- end  --------------------
[9] ~Delete
[0] ~Delete
[1] ~Delete
[2] ~Delete
[3] ~Delete
[4] ~Delete
[5] ~Delete
[6] ~Delete
[7] ~Delete
[8] ~Delete
[9] ~Delete

进程已结束,退出代码0

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高考我军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值