标准说有错,编译器说没有错!

skiffer 2003-08-29 01:44:15
发信人: Purusa (木偶机器人), 信区: CPlusPlus
标 题: 转贴一个C++问题
发信站: BBS 水木清华站 (Fri Aug 29 12:31:27 2003), 转信

一个小问题:
A temporary object of type T cannot be used as the actual parameter
for a function argument type T&, however, it can be used to invoke
a non-const member function of T, e.g.

struct A { void f() {} };

void g( A& ) {}

int main() {
A().f() ; // ok
g(A()) ; // error
}

why this inequity?

有人知道道理的还请指出,不确切知道的也来讨论一下:)

--
  乔峰吃了一惊:“好身手,这人是谁?”回掌护身,回过头来,不由得哑然失笑,
只见对面也是一条大汉单掌斜立,护住面门,含胸拔背,气凝如●,原来后殿的佛像
之前安着一座屏风,屏风上装着一面极大的铜镜,擦得晶光净亮,镜中将自己的人影
照了出来,铜镜上镌着四句经偈,佛像前点着几盏油灯,昏黄的灯光之下,依稀看到
是:“一切有为法,如梦幻泡影,如露亦如电,当作如是观。”


※ 来源:·BBS 水木清华站 smth.org·[FROM: 131.252.207.214]
...全文
92 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
skiffer 2003-09-10
  • 打赏
  • 举报
回复
高手进啊
lss9736 2003-09-10
  • 打赏
  • 举报
回复
sdkjfk

skiffer 2003-09-10
  • 打赏
  • 举报
回复
haha
Jinhao 2003-09-10
  • 打赏
  • 举报
回复
struct A { void f() {} }; //这里的f()是public:的

void g( A& ) {}

int main() {
A().f() ; // 所以ok
g(A()) ; // 因为A()是一个构造函数,返回的是一个临时对象,所以错了,但如果,是void g(const A&)就正确,这点在More Effective C++上的临时对象讲得很清楚,
}
sevecol 2003-09-10
  • 打赏
  • 举报
回复
临时对象应该只能帮定在const引用上面.
jp311 2003-09-10
  • 打赏
  • 举报
回复
■C++ Primer p461
主题:lvalue-to-rvalue 转换,rvalue-to-lvalue 转换。
讨论:lvalue-to-rvalue 属於完全吻合(exact match)转换的一种。
但是 rvalue-to-lvalue 呢?例如以一个 literal constant 或
temporary object 指派给一个 reference?应该不行,除非是
指派给一个 const reference。
测试结果:我的经验是,各编译器对此一主题宽紧不一,且无定法(至少我归纳不出)
例一:

#001 int main()
#002 {
#003 int &i = 3; // (1) should be error
#004 // rvalue assign to non-const reference
#005 const int &i2 = 3; // (2) should be ok
#006 // rvalue assign to const reference
#007 int &i3 = int(3); // (3) should be error
#008 // rvalue (temp obj) assign to non-const reference
#009 const int &i4 = int(3); // (4) should be ok
#010 // rvalue (temp obj) assign to const reference
#011 }
#012
#013 // G++ : (1),(3) warning: initialization of non-const reference `int &'
#014 // from rvalue `int'
#015 // jjhou 使用 G++ 2.91.57。
#016 // 据 jyhuang 说,G++ 2.92.2 并不允许通过 (1),(3)。
#017 //
#018 // VC6 : (1),(3) error: 'initializing' : cannot convert from 'const int'
#019 // to 'int &'. A reference that is not to 'const'
#020 // cannot be bound to a non-lvalue
#021 //
#022 // BCB4: (1),(2),(3),(4) warning: Temporary used to initialize 'i'
#023 // in function main ()

例二:

#001 void func1(int i) { }; // pass by value
#002 void func2(int& i) { }; // pass by reference
#003 void func3(int* i) { }; // pass by pointer
#004 void func4(const int& i) { }; // pass by reference
#005
#006 void main()
#007 {
#008 int i;
#009 const int ci = 5;
#010
#011 func1(i); // lvalue-to-rvalue, always ok.
#012 func1(ci);
#013 func2(i);
#014 func2(ci); // (15)
#015 func3(&i);
#016 func3(&ci); // (17)
#017 func4(i);
#018 func4(ci);
#019
#020 func2(int(6)); // (21), rvalue-to-nonconst-reference.
#021 func4(int(6)); // rvalue-to-const-reference, always ok.
#022 }
#023
#024 /*
#025 VC6 :
#026 (15) : error C2664: 'func2' : cannot convert parameter 1 from
#027 'const int' to 'int &'. Conversion loses qualifiers
#028 (17) : error C2664: 'func3' : cannot convert parameter 1 from
#029 'const int *' to 'int *'. Conversion loses qualifiers
#030 (21) : error C2664: 'func2' : cannot convert parameter 1 from
#031 'int' to 'int &'.
#032 A reference that is not to 'const' cannot be bound to a non-lvalue
#033
#034 BCB4 :
#035 Warning (15): Temporary used for parameter 'i' in call to 'func2(int &)'
#036 Error (17): Cannot convert 'const int *' to 'int *'
#037 Error (17): Type mismatch in parameter 'i' in call to 'func3(int*)'
#038 Warning (21): Temporary used for parameter 'i' in call to 'func2(int &)'
#039
#040 G++ :
#041 (15): warning: conversion from `const int' to `int &' discards const
#042 (3) : warning: in passing argument 1 of `func2(int &)'
#043 (17): warning: passing `const int *' as argument 1 of `func3(int *)' discards const
#044 (21): warning: initialization of non-const reference `int &' from rvalue `int'
#045 (3) : warning: in passing argument 1 of `func2(int &)'
#046 */

摘自侯sir“C++ 标准与实作之间”
http://jjhou.csdn.net/qa-cpp-primer-27.txt
jp311 2003-09-10
  • 打赏
  • 举报
回复
没有100%支持标准的编译器
ppby2002 2003-09-10
  • 打赏
  • 举报
回复
同意 oopig(面向对象的猪)
liao2001 2003-08-29
  • 打赏
  • 举报
回复
我也来灌水先!

所先,我们应该知道const与非const对象的区别,接下来我们就应该知道引入常成员函数的意义,如果我们将const对象作为非const来使用,这是很不安全的。
1。g(A());
g()的定义是要求一个非const,现在我们将一个const作为入参,安全由谁来保证?
2。a().f();
我认为正确的编译应该是不能通过的,因为f()是一个非常成员函数,现在由一个const对象来调用,这是不安全的。

xueweizhong 2003-08-29
  • 打赏
  • 举报
回复
我试了四个编译器,只有g++
认为
A& ref4=(A)10;//ok
是错误的。

你可以再去试一下www.comeaucomputing.com上的online compiler
回头我去翻一下标准,按我的直觉是
g++是正确的,其他编译器有点含糊其词的意思。


>vi a1.cpp
1 class A
2 {
3 public:
4 A(int){}
5 };
6
7 const A& ref1=10;//ok
8 A& ref2=10;//error const to not const
9
10 const A& ref3=(A)10;//ok
11 A& ref4=(A)10;//ok
12
13

<g++ -c a1.cpp
a1.cpp:8: initialization of non-const reference type `class A&' from rvalue of
type `int'
a1.cpp:11: initialization of non-const reference type `class A&' from rvalue of
type `A

<CC -c a1.cpp
"a1.cpp", line 8: Error: Initializing A& requires an lvalue.
1 Error(s) detected.

E:\>bcc32 -c a1.cpp
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
e:\a1.cpp:
Error E2357 e:\a1.cpp 8: Reference initialized with 'int', needs lvalue of type 'A'
*** 1 errors in Compile ***

E:\Microsoft Visual Studio\VC98\Bin>cl -c e:\a1.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

a1.cpp
e:\a1.cpp(8) : error C2440: 'initializing' : cannot convert from 'const int' to 'class A &'
A reference that is not to 'const' cannot be bound to a non-lvalue
stratagem 2003-08-29
  • 打赏
  • 举报
回复
8 test3.cpp
initializing non-const `A &' with `int' will use a temporary
11 test3.cpp
initialization of non-const reference type `class A &'




oopig 2003-08-29
  • 打赏
  • 举报
回复
编译测试的结果是:
BCB5.0: 通过
VC6.0: 通过
VC7.1: 通过
g++3.2: 错误
oopig 2003-08-29
  • 打赏
  • 举报
回复
sevecol(看什么看...):
我认为A& ref2 = A(10);和A& ref2 = (A)10;是一样的。
它们都可以在vc6下编译通过,原因大概是vc6对c++标准的支持问题。在c++标准规范中,这样的语句应该是不许可的。
这些也只是我的个人看法,请熟悉c++标准的大虾指正。
sevecol 2003-08-29
  • 打赏
  • 举报
回复
还有一个问题,我也想借这个机会问一问就是隐式转化和显式转化的结果是不是只存在const的特性不同?还是同时存在其它的不同?

比如:
class A
{
public:
A(int){}
};

const A& ref1=10;//ok
A& ref2=10;//error const to not const

const A& ref3=(A)10;//ok
A& ref4=(A)10;//ok
oopig 2003-08-29
  • 打赏
  • 举报
回复
临时对象不能被约束导非const引用。(《c++程序设计语言》)
A().f();//这里是对一个临时对象的函数调用,没有使用到非const引用,所以没有问题。
g(A());//使用了非const引用

例如:
const A &ref1 = A(); //ok
A &ref2 = A(); //error
至于原因,我认为是编译器对于const与非const引用不同处理对待有关。对于const refrence,编译器会把对象的析构放到ref生命期之后进行;而对于非const的refrence,编译器对于对象析构时机的选择,就不考虑那个非const的refrence。因为编译器的这个特性(应该说是c++语言标准的要求),不能够对临时对象使用非const引用。
oopig 2003-08-29
  • 打赏
  • 举报
回复
临时对象不能被约束导非const引用。(《c++程序设计语言》)
A().f();//这里是对一个临时对象的函数调用,没有使用到非const引用,所以没有问题。
g(A());//使用了非const引用

例如:
const A &ref1 = A(); //ok
A &ref2 = A(); //error
至于原因,我认为是编译器对于const与非const引用不同处理对待有关。对于const refrence,编译器会把对象的析构放到ref生命期之后进行;而对于非const的refrence,编译器对于对象析构时机的选择,就不考虑那个非const的refrence。因为编译器的这个特性(应该说是c++语言标准的要求),不能够对临时对象使用非const引用。
sevecol 2003-08-29
  • 打赏
  • 举报
回复
关注
fengfeng2003 2003-08-29
  • 打赏
  • 举报
回复
确实是这样

我想可能是因为显式调用A的构造函数生成一个临时变量
而g(A())是对临时变量的引用,即使对此临时变量进行了修改
出作用域后临时变量就消失了,也没太大意义,所以标准不允许
oopig 2003-08-29
  • 打赏
  • 举报
回复
void g(const A&) {}
blue风儿 2003-08-29
  • 打赏
  • 举报
回复
应该是先将struct实例化,再将实例扔给函数做参数,就OK了!!!
加载更多回复(2)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧