用自身初始化一个字符串(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&amp;,它一个引用。 @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++)的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中通过赋值初始化自己的 String 类

C++中的复制构造函数

C++中常用到的容器

c++类成员变量初始化详解

C++中string 的使用

Visual C++中二级指针的定义,初始化,赋值问题