クラスのフィールドを持つ奇妙な行動のstd ::ベクトルに追加します

Qq0:

私は、次のような状況で(打ち鳴らすとGCCの)いくつかの非常に奇妙な行動を発見しました。私は、ベクトルを持っているnodes一つの要素、クラスのインスタンスで、Node私は、上の関数を呼び出しnodes[0]、新規に追加し、そのNodeベクトルにします。新しいノードが追加されると、呼び出し元のオブジェクトのフィールドがリセットされ!しかし、彼らは関数が終了した後、再び正常に戻るように見えます。

私は、これは、最小限の再現性の例であると考えています。

#include <iostream>
#include <vector>

using namespace std;

struct Node;
vector<Node> nodes;

struct Node{
    int X;
    void set(){
        X = 3;
        cout << "Before, X = " << X << endl;
        nodes.push_back(Node());
        cout << "After, X = " << X << endl;
    }
};

int main() {
    nodes = vector<Node>();
    nodes.push_back(Node());

    nodes[0].set();
    cout << "Finally, X = " << nodes[0].X << endl;
}

どの出力

Before, X = 3
After, X = 0
Finally, X = 3

あなたが期待するもののXは、プロセスによって変更されないままにします。

私が試してみました他のもの:

  • 私は追加の行削除した場合Nodeの内部をset()、それがX = 3たびに出力します。
  • 私は新しいを作成した場合Nodeと、(その上でそれを呼び出すNode p = nodes[0])、出力は3、3、3です
  • 私は、参照を作成する場合Nodeと、(その上でそれを呼び出すNode &p = nodes[0])が出力されている3、0、0(参照はとき、ベクトルサイズ変更が失われているので、おそらくこの1つはあります?)

何らかの理由で、この未定義の動作ですか?どうして?

NathanOliver:

あなたのコードは未定義の動作を持っています。

void set(){
    X = 3;
    cout << "Before, X = " << X << endl;
    nodes.push_back(Node());
    cout << "After, X = " << X << endl;
}

アクセスがX本当にあるthis->Xthisベクトルのメンバーへのポインタです。あなたが行うときnodes.push_back(Node());、あなたはベクトルとそのプロセスの再割り当て、に新しい要素を追加し、すべてのイテレータ、ポインタと参照を無効にベクトルの要素に。その意味

cout << "After, X = " << X << endl;

使用されthisなくなった有効であることを。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=29612&siteId=1