C++ 左值右值

概述

左值和右值属于2中不同的表达式类型;它们在表达式中扮演不同的角色,特别是在赋值操作和函数参数传递中。

左值

定义:左值是指那些在内存中有确定位置的表达式,可以出现在赋值表达式的左侧,即可以被赋值。
特征:
左值可以出现在赋值操作的左侧,也可以出现在函数的参数中(如果函数参数是引用类型)。

关键点:表达式左边,可以被赋值可以推导出来;函数参数+参数是引用类型

右值

==定义:右值是指那些没有存储在内存中,或者没有持久存储位置的表达式。==它们通常表示临时值或字面量。
特征:右值通常不能出现在赋值操作的左侧,但C++11引入了右值引用(rvalue reference),允许右值出现在赋值操作的左侧,并且可以用于实现移动语义(move semantics)。

关键点:右值一般在表达式右边。

右值引用

定义:C++11引入了右值引用,用双写的&&表示,它允许程序员更有效地处理右值。
用途:

  1. 移动语义:允许临时对象的资源被“移动”到另一个对象中,而不是进行复制。一般用std::move来实现
  2. 完美转发:在模板编程中,可以转发参数的值类别(左值或右值)。 这个一般用std::forward来实现

示例1(移动语义):

#include <iostream>
#include <vector>

class ResourceHolder {
public:
    ResourceHolder(int size) : data(new int[size]) {
        std::cout << "ResourceHolder created with size " << size << std::endl;
    }

    ~ResourceHolder() {
        std::cout << "ResourceHolder destroyed" << std::endl;
        delete[] data;
    }

    // Move constructor
    ResourceHolder(ResourceHolder&& other) {
        data = other.data;
        other.data = nullptr;
    }

    // Copy constructor (deleted)
    ResourceHolder(const ResourceHolder&) = delete;

    // Move assignment operator
    ResourceHolder& operator=(ResourceHolder&& other) {
        if (this != &other) {
            delete[] data;
            data = other.data;
            other.data = nullptr;
        }
        return *this;
    }

    // Copy assignment operator (deleted)
    ResourceHolder& operator=(const ResourceHolder&) = delete;

private:
    int* data;
};

int main() {
    ResourceHolder largeResource(1024);
    std::vector<ResourceHolder> resources;

    // 使用 std::move 将 largeResource 移动到 vector 中
    resources.push_back(std::move(largeResource));

    // largeResource 现在是一个空的 ResourceHolder 对象
    return 0;
}

示例1(完美转发):

#include <utility>
#include <iostream>

// 假设这是我们要转发参数的目标函数
void process(int& i) {
    std::cout << "process(int&) called with " << i << std::endl;
}

void process(int&& i) {
    std::cout << "process(int&&) called with " << i << std::endl;
}

// 模板函数,使用 std::forward 来转发参数
template<typename T>
void wrapper(T&& arg) {
    process(std::forward<T>(arg));
}

int main() {
    int a = 5;
    wrapper(a);  // a 是左值,调用 process(int& i)
    wrapper(10); // 10 是右值,调用 process(int&& i)
}

左值和右值的互换

常量左值:通过const关键字可以创建一个常量左值,它不能被赋值。
右值转换为左值:通过赋值操作,右值可以转换为左值。例如,int &&a = 10; 这里的10是一个右值,但通过赋值操作,a成为了一个左值引用。

小结

本篇主要写了一个新的概念,右值引用;左值右值是一直存在的,只不过引入了一个右值引用,然后多了一个左值转成右值(一般用std::move),还多了一个完美转发(一般用std::forward)。例子仅供参考,理解概念使用。还是先把概念搞明白,然后才好理解;感兴趣可以一起学习学习。概念这东西,很多人都不喜欢,却都逃不掉,多看几遍就好了。OK,翻篇。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值