C ++ ostringstreamの奇妙な動作

ボリスラフ・ストイロフ

最近、C ++コードで非常に奇妙な問題が発生しました。ミニマリストの例でケースを再現しました。Eggクラスがあります:

class Egg
{
private:
    const char* name;
public:
    Egg() {};
    Egg(const char* name) {
        this->name=name;
    }
    const char* getName() {
        return name;
    }
};

卵を入れるバスケットクラスもあります

const int size = 15;
class Basket
{
private:
    int currentSize=0;
    Egg* eggs;
public:
    Basket(){
        eggs=new Egg[size];
    }
    void addEgg(Egg e){
        eggs[currentSize]=e;
        currentSize++;
    }
    void printEggs(){
        for(int i=0; i<currentSize; i++)
        {
            cout<<eggs[i].getName()<<endl;
        }
    }
    ~Basket(){
        delete[] eggs;
    }
};

したがって、これは期待どおりに機能する例です。

 Basket basket;
 Egg egg1("Egg1");
 Egg egg2("Egg2");

 basket.addEgg(egg1);
 basket.addEgg(egg2);
 basket.printEggs();
 //Output: Egg1 Egg2

これは期待どおりの結果ですが、ループ変数に応じて生成された名前でN個の卵を追加したい場合、次の問題が発生します。

 Basket basket;
 for(int i = 0; i<2; i++) {
    ostringstream os;
    os<<"Egg"<<i;
    Egg egg(os.str().c_str());
    basket.addEgg(egg);
 }
 basket.printEggs();
 //Output: Egg1 Egg1

ループ条件をi <5に変更すると、「Egg4 Egg4 Egg4Egg4Egg4」が表示されます。最後に追加されたEggを動的Egg配列のすべてのインデックスに保存します。

グーグルで検索したところ、Eggのchar * name変数に固定サイズを指定strcpyし、コンストラクターで使用すると問題が解決することがわかりました

これが「固定」のEggクラスです。

class Egg
{
private:
     char name[50];
public:
    Egg(){};
    Egg(const char* name)
    {
        strcpy(this->name, name);
    }
    const char* getName()
    {
        return name;
    }
};

さて、問題はなぜですか?

前もって感謝します。

ここでは、全体のコードへのリンクです。

一部のプログラマーの男

この式を詳しく見てみましょうos.str().c_str()

この関数strごとに文字列を返します。このように使用すると、返された文字列は、式の終わりまでしか存続しない一時オブジェクトになります。式が終了すると、文字列オブジェクトは破棄され、存在しなくなります。

コンストラクターに渡すポインターは、一時文字列オブジェクトの内部文字列へのポインターです。文字列オブジェクトが破棄されると、そのポインタは無効になり、それを使用すると未定義の動作が発生します。

もちろん、単純な解決策はstd::string、文字列を使用するときはいつでも使用することです。より複雑な解決策は、配列を使用して、文字列が消える前に文字列内容コピーすることです(「fixed」Eggクラスの場合と同様)。ただし、固定サイズの配列を使用する「固定」ソリューションでは、バッファオーバーフローが発生しやすいことに注意してください。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事