用自身初始化一个字符串(C++)
Posted
技术标签:
【中文标题】用自身初始化一个字符串(C++)【英文标题】:Initialize a string with itself (C++) 【发布时间】:2016-03-13 18:42:54 【问题描述】:以下代码可在 Linux (g++ 4.8.4) 和 Windows (VS Express 2013) 上编译,但执行时会产生不同的结果。
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
string str = str;
cout << "'str.length()': "
<< str.length() << endl;
return 0;
在 Linux 上我得到:
'str.length()': 140187593065792
在 Windows 上我得到:
'str.length()': 0
此外,如果我如下所示更改初始化语句,则它符合但在运行时崩溃(在 Linux 上,我得到:在抛出 'std::bad_alloc' 实例后调用终止):
string str = str + str;
我知道,在这两种情况下,这都不是初始化字符串变量的常用方法。但是,有人可以解释一下这段代码到底有什么问题吗?还有,为什么第一种情况下的输出不一样?
【问题讨论】:
这是未定义的行为。 相关(重复?):***.com/questions/9820027/… 【参考方案1】:当初始化器被评估时,str
已被声明,但尚未以任何方式构造。它的“价值”是完全不确定的。您的程序有未定义的行为。
【讨论】:
我不确定编译器会对此发出警告,将指针或引用传递给尚未初始化的对象是完全可以的。在这种情况下(构造函数是inline
),编译器可以内联函数并跟踪生命周期,但在一般情况下,我不会期望它。
@DavidRodríguez-dribeas: str
既不是指针也不是引用,这不是一般情况。话虽如此,我还是用 GCC 试了一下,它没有发出警告。
选定的构造函数将采用std::string const&
,它是一个引用。
@David:哦,对了。好的。不过,我希望get a warning for a built-in。【参考方案2】:
这段代码深陷未定义行为的境地。形式上,一旦看到对象的名称,它就在范围内并且可以用作初始值设定项。但是由于它的构造函数还没有运行,对象本身还没有被合理地初始化,并且在它自身之上复制构造它不一定会将它变成一个有效的对象。该发生的总会发生;不要那样做。
【讨论】:
【参考方案3】:从正式的角度来看,这是未定义的行为,您可能会就此结束。
从实际的角度来看,当你声明字符串的本地实例时,它的内存有随机值。因此,指向字符数组的指针无效,长度无效等。
为什么 VS 和 g++ 的结果不同?你可能在Debug模式下运行你的VS程序,VS可能会初始化一些东西What are some reasons a Release build would run differently than a Debug build
【讨论】:
我们坚持正式观察的原因是,实际证据可能比简单地观察内存中的字节更复杂和不可预测。编译器本可以利用这段代码中被自初始化破坏的优化机会,从而有效地破坏代码本身!阅读blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633以上是关于用自身初始化一个字符串(C++)的主要内容,如果未能解决你的问题,请参考以下文章