考虑一下这段代码(使用CString,因为它很熟悉,很容易看到没有构建,但没有什么特别的类),在Visual Studio 2008下测试:
CString DoSomething( const CString& sString )
{
return sString;
}
CString sTest1 = DoSomething( sTest1 ); // Compiles (no warnings), fails at runtime
CString sTest2( DoSomething( sTest2 ) ); // Doesn't compile
CString sTest3; sTest3 = DoSomething( sTest3 ); // Compiles, self-assignment, works
据我了解C ++标准,Test1可以作为编译时优化自动编译到Test2中,只要有适当的构造函数(默认情况下,它将生成与第一个测试相同)。但值得注意的是,行为与Test3不同,后者可以正常工作。
现在我明白为什么Test1不起作用,以及为什么Test2不能编译。我很好奇的是为什么Test1首先编译?这是允许的标准,开放的解释,VS2008的编译器的缺陷,初始使用前静态检查的缺陷,或什么?有没有办法强制编译器至少在这种情况下发出警告(Test1似乎在VS2008下用最大警告级别编译清理)?允许这种结构的C ++规范的理由是什么?
编辑:或者,有没有办法强制编译器将Test1编译为Test2(从而触发错误)?
编辑以为Test2添加逐字错误消息: 错误C2065:'sTest2':未声明的标识符
答案 0 :(得分:4)
您在sTest1中看到的行为在C ++标准中是未定义的。这很奇怪而且错了,但它编译在一些编译器上。
有关详细信息,请参阅以下主题中的litb答案:method running on an object BEFORE the object has been initialised?
答案 1 :(得分:3)
过去几天有几个关于相关现象的问题。
我的理解是,即使sTest1未初始化,它已经是一个有效的标识符(例如,在C中你可以调用sizeof),它只是没有内容。 因此,当您调用DoSomething时,您将传递对未初始化变量的引用,该变量是合法但危险的。
我猜测返回是运行时的问题,因为您正在尝试执行本质上应该是字符串的未初始化内存空间的值返回(复制构造函数)。根据CStrings的存储方式,代码可能正在查找空终止符或表示已分配字节数的内容。