免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7933 | 回复: 17
打印 上一主题 下一主题

[C++] 关于C++中的临时变量的讨论 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-10-02 10:54 |只看该作者 |倒序浏览
在thinking in C++中有这么一段代码,在vc6上是可以通过编译的,但百思不得其解:

class X {
        int i;
public:
        X(int I=0):i(I) {}
        void modify(){i++;}
};

X f5() {
        return X();
}

const X f6() {
        return X();
}

void f7(X& x) {
        x.modify();
}

void main() {
        f5() = X(1);
        f5().modify();
        f7(f5());
}

问题:难道f5()的返回值不是临时对象吗?临时对象不是被编译器作为常量看待吗?为什么还可以做左值?
请各位大虾指点迷津!

[ 本帖最后由 thinshootout 于 2007-10-3 15:55 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-10-02 14:42 |只看该作者
是传值!而且返回类型没有const修饰!能做lvalue的.
我记得thinking in c++讨论临时对象的时候,对native数据类型,和用户自定义类型是分别说明的.
.........嗯.......我记得是...

论坛徽章:
0
3 [报告]
发表于 2007-10-02 18:47 |只看该作者
f7(f5());这个是错的
因为f5()返回一个临时对象,而对临时对象的引用只能const引用

论坛徽章:
0
4 [报告]
发表于 2007-10-02 19:45 |只看该作者

回复 #3 tyc611 的帖子

to 3楼
我也是这么认为的,可是在vc6中编译居然可以通过,不解中

论坛徽章:
0
5 [报告]
发表于 2007-10-02 21:00 |只看该作者
>> 难道f5()的返回值不是临时对象吗?

是。

>> 临时对象不是被编译器作为常量看待吗?

除非是一个 const 类型的临时对象,否则不是常量。把临时对象等同于常量是一个常见的误解,可参考我在这个帖子中的说明:http://bbs.chinaunix.net/viewthread.php?tid=993395

>> 为什么还可以做左值?

f5() = X(1); 中的 f5() 不是一个左值表达式,它是一个右值。如果函数的返回类型不是引用,那么函数调用的结果总是一个右值。

C++ 中改变一个右值是合法的,如果它是一个类对象的话。

>> 在thinking in C++中有这么一段代码,在vc6上是可以通过编译的,但百思不得其解

因为 VC6 允许将右值绑定在非 const 引用上,这是它的一个扩展功能(可以在设置中屏蔽扩展功能)。C++ 标准不允许这样做,为此,在以后版本的 VC++ 中会对此给出诊断信息。

论坛徽章:
0
6 [报告]
发表于 2007-10-03 09:39 |只看该作者

回复 #5 whyglinux 的帖子

感谢 whyglinux,使我发现了我之前对语法的一些误解,现归纳如下,一来请 whyglinux 兄审校,二来以备查阅,三来希望能够对其他同仁有所帮助。

首先明确几个概念(个人理解,可能不太严谨):

临时对象:对于某对象,如果未被通过定义变量来显式分配地址,而是由编译器临时分配内存空间,并负责释放内存空间,则该对象即为“临时对象”。

常量:通过const关键字修饰的(应与“文字量”相区别),表示不会变化的值。

左值:引用某个对象的表达式(摘自The C++ Programming Language)。并不是每个左值都能够被用在赋值的左边,左值也可以是引用了某个常量。没有被声明为常量的左值常被称为“可修改的左值”(可寻址)。

右值:变量的数据值,存储在某个内存地址中(摘自C++ Primer)。右值只是一个表达式,它表示了一个值或一个引用了临时对象的表达式,用户不能寻址该对象,也不能改变它的值(根据 whyglinux 兄的描述,类对象为特例,但我在文献中并未找到此说明,有待进一步确认)。



概念之间的关系:

临时对象与常量:除非是一个 const 类型的临时对象,否则不是常量。只不过临时变量不能被约束到非const引用。

左值与右值:左值不一定允许被修改(即不一定允许放在赋值运算符左边),右值不一定不允许被修改(即不一定不允许放在赋值运算符左边),表示常量引用的左值不允许被修改,表示类对象的右值(如通过函数调用返回)允许被修改。

const引用:对于常量的引用固然要进行 const 引用,对于右值的引用、对于不兼容类型的对象的引用等都只能进行const引用。

[ 本帖最后由 thinshootout 于 2007-10-3 09:42 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2007-10-03 10:45 |只看该作者
原帖由 thinshootout 于 2007-10-3 09:39 发表
[quote]右值只是一个表达式,它表示了一个值或一个引用了临时对象的表达式,用户不能寻址该对象,也不能改变它的值(根据 whyglinux 兄的描述,类对象为特例,但我在文献中并未找到此说明,有待进一步确认)。

[/quote]
你1楼的例子: f5() = X(1);不就说明了右值也是可改变的吗?还有你下面的总结也说明了这点,为啥要自相矛盾呢?
右值不一定不允许被修改(即不一定不允许放在赋值运算符左边),表示常量引用的左值不允许被修改,表示类对象的右值(如通过函数调用返回)允许被修改。

论坛徽章:
0
8 [报告]
发表于 2007-10-03 11:36 |只看该作者

回复 #7 tyc611 的帖子

右值只是一个表达式,它表示了一个值或一个引用了临时对象的表达式,用户不能寻址该对象,也不能改变它的值

这句话是从C++ Primer上原封不动摘下来的

论坛徽章:
0
9 [报告]
发表于 2007-10-03 11:43 |只看该作者
原帖由 thinshootout 于 2007-10-3 11:36 发表
右值只是一个表达式,它表示了一个值或一个引用了临时对象的表达式,用户不能寻址该对象,也不能改变它的值

这句话是从C++ Primer上原封不动摘下来的

第几版?章节?我看看去

论坛徽章:
0
10 [报告]
发表于 2007-10-03 11:50 |只看该作者

回复 #9 tyc611 的帖子

C++ Primer第三版第9.3.1节第4段
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP