2016-04-11 1 views
1

std::vector<A*>に2つ以上の項目を追加すると、追加された項目のメンバの値が変わりますここ
Minimal, Complete and Verifiable Example次のとおりです。スタックに割り当てられた要素のポインタをstd :: vectorにプッシュすると、そのメンバの値が変更されます

#include <iostream> 
#include <vector> 

struct B; 

struct C 
{ 
    float x; 

    C(float x) 
    { 
     this->x = x; 
    } 
}; 

struct A : public C 
{ 
    bool begin; 
    bool visible; 
    B* b; 

    A(float x, B* parent) 
     : C(x) 
    { 
     begin = false; 
     visible = false; 
     b = parent; 
    } 
}; 

struct B 
{ 
    A a1; 
    A a2; 

    B(float x1, float x2) 
     : a1(x1, this), a2(x2, this) 
    { 
     a1.visible = true; 
    } 
}; 

int main() 
{ 
    std::vector<B> bs; 
    std::vector<A*> as; 
    bs.push_back(B(1, 2)); 
    as.push_back(&bs.back().a1); 
    as.push_back(&bs.back().a2); 
    bs.push_back(B(2, 3)); 
    as.push_back(&bs.back().a1); 
    as.push_back(&bs.back().a2); 

    for(auto& it : as) 
    { 
     std::cout << it->begin << std::endl; 
    } 

    std::cin.get(); 

    return EXIT_SUCCESS; 
} 

上記のコードの別の問題(それはすでにtobi303でコメントで述べました)があります: 構造体AからポインタB* bBのインスタンスをコピーによるpush_back(B(...))に無効となるが、 、解決策はを使用することです代わりに

+0

正確なコードとサンプルの出力を不思議な2つのセグメントで入力できますか? 補足として、いくつかのフィールドはinit-listで初期化され、他のフィールドは本体で割り当てられます。 – bipll

+0

これが問題に関係しているのかどうかはわかりませんが、 'Endpoint'が' Segment'へのポインタを保持していることに気がつきましたが、セグメントを 'vector'に置くとコピーが作成され、あなたが押した一時的なものを指している)。 'emplace_back'はその問題を解決するかもしれません。 – user463035818

+0

それ以外はあまりありません。私はちょうどテストしていましたが、すべてのコードを追加することができます(私は短縮する方が良いと思いました)。私はiniatializerのリストを混ぜて本文に初期化すると問題だと教えてもらえますか? – sro5h

答えて

4

問題は、より多くの要素がベクトルに追加されると、サイズが変更される可能性があるということです。これが起こると、すべての要素が新しい場所に移動され、既存のすべてのポインタと要素への参照が無効になります。

std::listboost::stable_vectorのように、新しい要素が追加されたときにイテレータを無効にしないコンテナがあります。

I.e. Segment要素の連続した記憶域を必要としない場合は、std::stable<Segment>の代わりにboost::stable_vector<Segment>またはstd::list<Segment>を使用して問題を解決します。

関連する問題