快速业务通道

C++中关于左值和右值的讨论

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
要求是左值数组,上述表达式合法。另外,在这里f()虽然是右值,但是f()却引用到一个对象,我们通过f()。c[0]左值表达式可以引用到该对象的一部分,并且通过(*)可以修改它(因为该左值表达式是modifiable lvalue,但是尝试修改它的行为是未定义的,然而从左右值性上是行得通的 )

* 关于数组类型

数组类型在大部分场合都会退化为一个指向其首元素的指针(右值),因而在左右值性和类型判断上,容易发生误解。数组不发生退化的地方有几个场合,一是声明时;一是用作sizeof的操作数时;一是用作&取址运算的操作数时。

Ex1.8

int a[3]={1,2,3};
int b[3];
b=a; //error. b converted to int* (rvalue): array degration.
int* p=a; //array degration: a converted to an rvalue of int*
sizeof(a); // no degration.
&a; //no degration.

C++中,数组还有其他场合不发生退化,比如作为引用的initializer;作为typeid/ typeinfo的操作数和模板推导时。

2 C++的左值

2.1

与C不同的是,C++中,一个左值表达式,不仅可以引用到对象,同样也可以引用到一个函数上。假定f是一个函数名,那么表达式f就表示一个左值表达式,该表达式引用到对应的函数;void (*p)(void); 那么*p也是一个左值。然而一个函数类型的左值是不可修改的。 *p=f;// error. (注:类的non-static member function,不是这里指的函数类型,它不能脱离对象而存在; 而static member function是函数类型)

另一个不同之处在于,对于register变量,C++允许对其取址,即register int i; &i;这种取址运算,事实上要求C++编译器忽略掉register specifier指定的建议。无论在C/C++中, register与inline一样都只是对编译器优化的一个建议,这种建议的取舍则由编译器决定。

C++中,一个右值的class type表达式,引用到一个对象;这个对象往往是一个临时对象(temporary object)。在C++中,我们可以通过class type的右值表达式的成员函数来间接修改对象。

Ex2.1
class A
{
int i,j;
public:
void f(){ i=0; }
void g() const { i; }
};

A foo1();
const A foo2();

A().f(); //ok, modify the temporary object.
A().g();//ok, refer to the temporary object.

foo1().f();//ok, modify the temporary object.
foo1().g();//ok, refer to the temporary object.

typedef const A B;
B().f(); //error. B()'' s an rvalue with const A,
B().g(); //ok, refer to the temporary object.

foo2().f();//error. B()'' s an rvalue with const A,
foo2().g();//ok, refer to the temporary object

需要再次说明的是,C++中的class type的右值表达式可以具有const/volatile属性,而在C中右值总是cv-unqualified.

Ex2.2
struct A{ char c[2]; };
const struct A f();

在C中,f()的返回值总是一个右值表达式,具有struct A类型(const被忽略)。

2.2

C++中引入了引用类型(reference type),引用总是引用到某一对象或者函数上,因此当我们使用引用时,相当于对其引用的对象/函数进行操作,因而引用类型的表达式总是左值。

(在分析表达式类型时,如果一个表达式expr最初具有T&类型,该表达式会被看作具有类型T的左值表达式)

Ex2.3
extern int& ri;
int & f();

int g();
f()=1;
ri=1;
g()=1;// error.

函数调用f()的返回类型为int&, 因此表达式f()的类型等价于一个int类型的左值表达式。

而函数调用g()的返回类型为int,因此表达式g()为int类型的右值表达式。

与C++相比,C中函数调用的返回值总是右值的。

2.3 与C相比,在C++中,转换表达式可能产生左值。如果转换的目标类型为引用类型T&,转换表达式的结果就

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号