首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

编译器的差异:临时对象做实参的可能编译不过?该如何处理

2012-03-15 
编译器的差异:临时对象做实参的可能编译不过?下面的代码在vs2005可正常编译运行,但gcc似乎不行(偶用的cygw

编译器的差异:临时对象做实参的可能编译不过?
下面的代码在vs2005可正常编译运行,但gcc似乎不行(偶用的cygwin),虽然vs2005对标准C++的支持已经有很大进步了。。

gcc版本如下:

D:\cygwin\bin> gcc   -v
Reading   specs   from   /usr/lib/gcc/i686-pc-cygwin/3.4.4/specs
Configured   with:   /gcc/gcc-3.4.4/gcc-3.4.4-1/configure   --verbose   --prefix=/usr   --exec-prefix=/usr   --sysconfdir=/etc   --lib
dir=/usr/lib   --libexecdir=/usr/lib   --mandir=/usr/share/man   --infodir=/usr/share/info   --enable-languages=c,ada,c++,d,f77,
java,objc   --enable-nls   --without-included-gettext   --enable-version-specific-runtime-libs   --without-x   --enable-libgcj   --d
isable-java-awt   --with-system-zlib   --enable-interpreter   --disable-libgcj-debug   --enable-threads=posix   --enable-java-gc=b
oehm   --disable-win32-registry   --enable-sjlj-exceptions   --enable-hash-synchronization   --enable-libstdcxx-debug   :   (reconfi
gured)
Thread   model:   posix
gcc   version   3.4.4   (cygming   special)   (gdc   0.12,   using   dmd   0.125)


言归正传,

问题一:

void   fun2(string   &str)
{
        cout   < <   str   < <   endl;
}

int   main()
{
        fun2(string( "hello,   "));
}

gcc编译错误提示如下:
D:\cygwin\home\ADMINI~1\project\aboutCPP.cpp:   In   function   `int   main() ':
D:\cygwin\home\ADMINI~1\project\aboutCPP.cpp:35:   error:   invalid   initialization   of   non-const   reference   of   type   'std::string& '   from   a   temporary   of   type   'std::string '
D:\cygwin\home\ADMINI~1\project\aboutCPP.cpp:28:   error:   in   passing   argument   1   of   `void   fun2(std::string&) '

为什么非法?看起来似乎是由于临时对象是一个const对象?真的吗?

答案是否定的,下面的代码可以说明之:

class   MyString
{
public:
        int   Data()   {   return   m_data;   }
        MyString   &Data(int   val)   {   m_data   =   val;   }
private:  
        int   m_data;
};

int   main()
{        
        cout   < <   MyString().Data(2).Data()   < <   endl;
}

说明临时对象是non-const的!

另外,无意中又发现一个问题。

问题二:

class   MyString
{
public:
        int   Data()   {   return   m_data;   }
        MyString   &Data(int   val)   {   m_data   =   val;   }
private:  
        int   m_data;
};

int   main()
{
        MyString   conMyStr;
        const   MyString   conMyStr2;
}

gcc编译报错如下:
D:\cygwin\home\ADMINI~1\project\aboutCPP.cpp:   In   function   `int   main() ':
D:\cygwin\home\ADMINI~1\project\aboutCPP.cpp:51:   error:   uninitialized   const   `conMyStr2 '

gcc对const的支持有问题吗(瞎猜的,怎可能)?这个错又怎么解释?

小弟比较穷,分不多,但暂时也找不到好的解释办法。

哪位大侠可指点一下,谢谢~!

[解决办法]


关于标准的解释
Initialization of a reference is trivial when the initializer is an
lvalue (an object whose address you can take; see §4.9.6). The
initializer for a 'plain ' T& must be an lvalue of type T. The
initializer for a const T& need not be an lvalue or even of type T.
In such cases (David ' 's notes: and only in such cases),
[1] first, implicit type conversion to T is applied if necessary (see §C.6);
[2] then, the resulting value is placed in a temporary variable of type T; and
[3] finally, this temporary variable is used as the value of the initializer.
Consider:
double& dr = 1; // error: lvalue needed
const double& cdr = 1; // ok
The interpretation of this last initialization might be:
double temp = double(1) ; // first create a temporary with the right value
const double& cdr = temp; // then use the temporary as the initializer for cdr
A temporary created to hold a reference initializer persists until
the end of its reference’s scope.
References to variables and references to constants are distinguished
because the introduction of a temporary in the case of the variable
is highly errorprone;
an assignment to the variable would become an assignment to the –
soon to disappear – temporary. No such problem exists for references
to constants, and references to constants are often important as
function arguments (§11.6).
[解决办法]
to Jofee(阿飞) ,请注意这一段的理解:

because the introduction of a temporary in the case of the variable
is highly errorprone;
an assignment to the variable would become an assignment to the –
soon to disappear – temporary. No such problem exists for references
to constants

第一句说的易出错指的是逻辑错误,而不是“临时对象销毁之后引用无效”,如果我没记错的话,C++中不存在无效引用。出了作用域,临时对象与引用一同消失。
这里第二句是关键:向一变量赋值可能导致赋值到一个马上就要消失的临时变量上去,而对于常量引用不存在这个问题。
很明显,问题就在于,向一个马上就要消失的变量赋值没有起到期望的作用,常量引用没问题是因为常量引用不允许赋值。

热点排行