免费注册 查看新帖 |

Chinaunix

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

临时量的一点问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-12-23 11:56 |只看该作者 |倒序浏览
编译器把所有的临时量自动成为CONST,改变临时量是错误的。
然而为什么下面是对的???
X f5(){
return X();
}
void f7(X &x);
....
f7(f5);
f(5)=X();
f(5).modify();//好像改变了临时量的直啊。。



还有
const int f4(){return 1;}
为什么int k=f4();是对的,不是说要CONST INT K=F4();才可以嘛??



什么叫常量折叠???

论坛徽章:
0
2 [报告]
发表于 2007-12-23 14:59 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
3 [报告]
发表于 2007-12-23 16:45 |只看该作者
编译器把所有的临时量自动成为CONST,改变临时量是错误的

这句话有点问题,临时变量自动成为const,没听说过。
可以改变临时变量的,不过你的修改在 full-expression计算完毕后丢弃,不能继续使用了。
TC++PL charpter 10.4.10 专门讨论临时变量,看看吧

论坛徽章:
0
4 [报告]
发表于 2007-12-23 16:55 |只看该作者
int k = f4();
临时变量,const变量都可以是右值啊,
没听说过const返回值不可以是右值的。

论坛徽章:
0
5 [报告]
发表于 2007-12-23 16:56 |只看该作者
以下是google的结果,回答楼主常量折叠的问题

常量折叠

在程序编译期间,在可能的情况下,符号常量的值会替换该名字的出现。这个替代过程被称为常量折叠(constant folding)。对于符号常量,编译器缺省不会为它分配存储空间,而是把它保存在符号表中,当在程序的其它地方用到这个符号常量时,编译器用初始化这个符号常量的值来替代它。回到刚才的小程序:

        const int a=0;     // 定义了一个符号常量a                                                               
            .....
        cout<<a<<endl;     // 这个地方编译器用0代替a,等价于cout<<0<<endl;

在VC下可以查看disassembly下的汇编代码可以证明这一点。

上面刚才提到对于符号常量编译器缺省是不为其分配存储空间的,但程序中却可以强制要求编译器为其分配存储空间,比如显示的用到了符号常量的地址,这时编译器将为其非配存储空间,比如上面的小程序中就分配了存储空间。

        cout<<&a<<endl;    // 显示引用了&a,编译器分配存储空间。
只是这个存储空间分配后存在于程序的某一地方,除非你显示的去引用它,否则符号变量a和它一点关系都没有。后来我又试了如下语句 cout<<*(&a)<<endl;结果还是0;我想这是因为&a是个const int *,所以编译器对 *(&a)还是用0来替代的,但是如果作了强制类型转换,即cout<<*(int*)(&a)<<endl; 后,输出结果就是100了,这也说名强制类型转换将const int *转换为int *后显示的引用了为a分配的内存,编译器按照处理普通变量地址的方式来输出*(int*)(&a);
因为常量折叠只是作替代,所以如果想到前一段时间版上讨论的重复定义的问题,就应该可以知道,符号常量不会出现重复定义的问题,即你可以在头文件中定义符号常量,然后任意的包含在cpp文件中,link的时候也不会出错,甚至可以在任意cpp文件中定义同名的符号常量也不会有问题。有的书上解释是对于const型变量,编译器采用的是内部连接,也就是说const型变量只在其定义过的文件中是可见的,而在连接时其它编译单元无法看到,所以 link的时候不会出问题。

[ 本帖最后由 redhat008 于 2007-12-23 16:59 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2007-12-23 17:47 |只看该作者

回复 #3 redhat008 的帖子

Returning by value as a const becomes important when you’re
dealing with user-defined types. If a function returns a class object
by value as a const, the return value of that function cannot be an
lvalue (that is, it cannot be assigned to or otherwise modified).

论坛徽章:
0
7 [报告]
发表于 2007-12-23 17:49 |只看该作者

回复 #4 redhat008 的帖子


记错了。。

int d = 1;
const int e = 2;
int* u = &d; // OK -- d not const
//! int* v = &e; // Illegal -- e const"

论坛徽章:
0
8 [报告]
发表于 2007-12-23 18:02 |只看该作者

回复 #5 redhat008 的帖子

谢谢redhat008
不过"cout<<*(int*)(&a)<<endl; 后,输出结果就是100了,"什么意思啊?怎么就是100了啊???

论坛徽章:
0
9 [报告]
发表于 2007-12-23 18:45 |只看该作者

回复 #6 3040602024 的帖子

不知道你这个从哪看到的?
感觉作者是从应该怎么样的角度去说的,意思是你应该当作const object处理,就像数组指针越界一样,数组a[n],你使用a,你应该保证a必须是数组有效元素,但是实际上你可以使用a[n+1],a[n+2].....
《The C++ Programming Language》10.4.10 临时变量 很权威的

论坛徽章:
0
10 [报告]
发表于 2007-12-29 21:50 |只看该作者
>> 编译器把所有的临时量自动成为CONST,改变临时量是错误的。

上述说法显然是错误的。不要认为不能被改变的就一定是 const 限定对象或者常量的(比如 x + y 表达式也是不可被改变的)。

另外,没有所谓的“临时量”这一术语,正确的应该是“临时对象(Temporary Object)”。“临时变量”的说法也是不规范的,因为在 C++ 中“变量(Variable)”指的是有名字的对象,而临时对象是没有名字的。

>> f(5).modify();//好像改变了临时量的直啊。。

如果临时对象是类(Class)类型,并且没有 const 限定,那么它是可以被改变的。因此,上面的操作是合法的。非类类型的临时对象不能被改变,这样做是为了与 C 兼容。

>> const int f4(){return 1;}
>> 为什么int k=f4();是对的,不是说要CONST INT K=F4();才可以嘛??

两者都对。因为 f4() 的结果是一个 int 类型的值,在上面都是用同一个值来对 k 进行初始化。其实对有 const 限定的对象如果使用的是它的值语义(即转换为右值),在值中已经没有 const 的概念了,因为 const 限制的是作为左值的对象,以防止直接给对象赋值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP