web-dev-qa-db-ja.com

ここで#include <string>がスタックオーバーフローエラーを防ぐのはなぜですか?

これは私のサンプルコードです。

#include <iostream>
#include <string>
using namespace std;

class MyClass
{
    string figName;
public:
    MyClass(const string& s)
    {
        figName = s;
    }

    const string& getName() const
    {
        return figName;
    }
};

ostream& operator<<(ostream& ausgabe, const MyClass& f)
{
    ausgabe << f.getName();
    return ausgabe;
}

int main()
{
    MyClass f1("Hello");
    cout << f1;
    return 0;
}

#include <string>をコメントアウトすると、コンパイラエラーは発生しません。これは、#include <iostream>を介して含まれているためです。 I "右クリック->定義に移動" Microsoft VSでは、両方ともxstringファイルの同じ行を指します。

typedef basic_string<char, char_traits<char>, allocator<char> >
    string;

しかし、プログラムを実行すると、例外エラーが発生します。

OperatorString.exeの0x77846B6E(ntdll.dll):0xC00000FD:スタックオーバーフロー(パラメーター:0x00000001、0x01202FC4)

#include <string>をコメントアウトするときにランタイムエラーが発生する理由は何ですか? VS 2013 Expressを使用しています。

121
airborne

問題は、コードが無限再帰を実行していることです。 std::stringstd::ostream& operator<<(std::ostream&, const std::string&))のストリーミング演算子は<string>ヘッダーファイルで宣言されていますが、std::string自体は他のヘッダーファイル(<iostream><string>)。

<string>を含めない場合、コンパイラはausgabe << f.getName();をコンパイルする方法を見つけようとします。

MyClassのストリーミング演算子とstd::stringを許可するコンストラクターの両方を定義したため、コンパイラーは( 暗黙の構築 を使用して)再帰呼び出しを作成します。 。

explicitコンストラクター(explicit MyClass(const std::string& s))を宣言すると、ストリーミングオペレーターをstd::stringで呼び出す方法がないため、コードはコンパイルされなくなり、 <string>ヘッダーを含めます。

編集

私のテスト環境はVS 2010であり、警告レベル1(/W1)から開始して、問題について警告します。

警告C4717: 'operator <<':すべての制御パスで再帰的、関数によりランタイムスタックオーバーフローが発生します

35
cbuchart