C++ 值类型之左值

本文详细介绍了C++中的左值,包括变量、函数调用、赋值表达式等多种形式,并提到了未决成员函数调用的概念。讨论了左值在函数调用、表达式中的角色以及右值引用与左值的关系。

总之,能取址的一定是左值,除位域寄存器变量(即register变量,但最新的编译器,如gcc,遇到代码中对register变量使用&取址时,会自动转换成普通变量,即register关键字被忽略了)以外,左值皆可取址,即能使用&取址运算符。

以下列表所有左值:

1.  变量,函数名,成员变量名,无论其类型,即使变量类型是右值引用,其名字构成的表达式仍是左值表达式。注意:

void setValue(int&& value) {
}

void transferValue(int&& value) {
    setValue(a);  // error, No matching function for call to 'setValue'
}

void transferValue(int&& value) {
    setValue(std::move(value)); // ok
}

2. 函数调用或重载运算符表达式,其返回类型为左值引用。如std::cout << 1,  str1 = str2, ++i等

// 返回左值引用
int& handleValue(int& value) {
    return value;
}

3. 所有内建(即非重载)的赋值及复合赋值表达式,因为表达式实际返回的是左值引用。如a = b,a += b,a %= b。

4. 内建的前置自增和自减表达式,即++a,--a。注意:此处是前置,后置自增和自减为纯右值。

5. 内建的间接寻址表达式,即*p,因为&(*p) == p。

6. 内建的下标表达式,即a[n] 和 p[a],但数组a必须是左值。

7. 对象成员表达式,即a.m,但m如果是成员枚举项(不是枚举变量)或者是非静态成员函数(参见下面的未决成员函数调用),或者a为右值且m为非引用类型的非静态数据成员,则a.m表达式为纯右值。


public:
    enum Color {
        Red //成员枚举项
    };
    
    void fun() {
        std::cout << "fun()" << std::endl;
    }
    
    static int sValue;  // 静态数据成员
    int value = 0;  // 非静态数据成员
    int& r = value; // 引用类型
};

Test getTest() {
    return Test();
}

int main(int argc, const char * argv[]) {
    Test t;  // t.Red 是右值,
             // t.fun 是右值,但这个表达式是不能初始化引用,参见“未决成员函数调用”
    getTest().value;    // 右值
    getTest().sValue;   // 左值
    getTest().r         // 左值
    return 0;
}

8. 内建的指针成员表达式,即p->m,但m如何是成员枚举项(不是枚举变量)或者是非静态成员函数(参见下面的未决成员函数调用),则p->m表达式为纯右值。

9. 对象成员指针表达式,即a.*mp,a必须是左值,且mp是数据成员指针。

typedef int (Test::*MP); // 数据成员指针
MP mp = &Test::value;
Test t;
t.*mp; // 左值

10. 内建的指针的成员指针表达式,即p->*mp,且mp是数据成员指针。

11. 内建的逗号表达式,即(a,b),且b为左值(内建的逗号表达式返回是最右边的值)

12. 三元条件表达式,即 a ? b : c,至于其什么情况为左值,详见条件表达运算符,个人经验是当b和c都是左值时,表达式才是左值,否则是右值(纯右值或亡值)

13. 字符串字面量,例如:"ant"

14. 转换成左值引用类型的转型表达式,例如static_cast<int&>(x)

15. 返回类型为函数右值引用的函数调用表达式或者重载的运算符表达式,如void (&&) () 为返回空参数空的函数右值引用。

16. 转换为函数右值引用类型的转型表达式,如static_cast<void(&&)()>(x)。

未决成员函数调用(Pending member function call)

表达式 a.mf 与 p->mf,其中 mf 是非静态成员函数,以及表达式 a.*pmf 与 p->*pmf,其中 pmf 是成员函数指针,被归类为纯右值表达式。但它们不能用来初始化引用,也不能作为实参,只能用来作为函数调用运算符的左操作数(即p.mf(args)),总之我理解的就是无法验证它是右值,但是它就是右值

参考:https://en.cppreference.com/w/cpp/language/value_category

加入我们:http://www.duoceshi.com/team.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值