2013-11-23 7 views
6

私のC++コードには、int型のidフィールドを持つクラスオブジェクトがあります。今私はObject *型のポインタのベクトルを作成したいと思います。最初に試しましたポインタのC++ベクトルを作成する

vector<Object*> v; 

for(int id=0; id<n; id++) { 
    Object ob = Object(id); 
    v.push_back(&ob); 
} 

しかし、ここでは同じアドレスがn回だけ繰り返されるため、これは失敗しました。私が新しい演算子を使用した場合、私が望むものを得ることができますが、動的メモリ割り当てを避けたいと思います。それから、私は必要なものがforループの前にn個の異なるポインタを宣言することだと思った。これに簡単な方法は、私がこれをしなかったので、配列を宣言することです:

vector<Object*> v; 
Object ar[n]; 

for(int i=0; i<n; i++) { 
    ar[i] = Object(i); 
} 

for(int i=0; i<n; i++) { 
    v.push_back(ar+i); 
} 

はまだ私はそれをこのように行うとメモリリークを取得する可能性がありますか?また、配列宣言を行うことは、私の意見では少し不器用です。ポインターのベクトルを作成する他の方法はありますか?手動でのメモリ管理は避けてください。

EDIT:単純なオブジェクトの代わりにポインタを使用するのはなぜですか?

私はこのように思っていたので、元の実際の状況を少し変更しました。これは、可能な限り単純な形式で質問を表すことができます。とにかく、なぜ私はポインターのベクトルが欲しいのか分からずに質問に答えられると思う。

は、実際に私は、私はタイプObjectのオブジェクトとメンバーフィールドvecを埋めたい派生クラスB

Class A { 
protected: 
    vector<Superobject*> vec; 
... 
}; 

Class B: public A {...}; 

Class Superobject { 
protected: 
    int id; 
... 
} 

Class Object: public Superobject {...} 

を持っています。スーパークラスがポインタを使用しなかった場合、私はオブジェクトのスライスに問題があります。だからクラスBのコンストラクタでObject*のポインタのベクトルとしてvecを初期化したいと思います。

EDIT2

はい、動的な割り当てが合理的選択肢であるように私には思えるし、配列を使用するという考えは悪い考えです。配列が有効範囲外になると、ベクター内のポインタがオブジェクトを必ずしも必要としないメモリ位置を指し示すため、事態はうまくいかなくなります。

は、クラスBのコンストラクタでは、私は
B(int n) { 
    vector<Object*> vec; 
    Object ar[n]; 

    for(int id=0; id<n; id++) { 
     ar[id] = Object(id); 
    } 

    for(int id=0; id<n; id++) { 
     v.push_back(ar+id); 
    } 
} 

これは

+2

動的メモリ割り当てをしたくない場合は、なぜポインタを使用していますか?また、Objectの配列を操作することもできます。 –

+1

なぜポインタを最初に格納したいのですか? – Yuushi

+1

2番目の方法の問題は、それが正当なC++ではないということです。 'Object ar [n];'は、nが定数でない限り正当ではありません。また、あなたの編集によれば、クラス階層がありますが、 'Object ar [n];であるので、あなたはスーパーオブジェクトではなくオブジェクトしか持っていません。あなたが破壊されたオブジェクトのアドレスを格納しているという理由で、最初の方法も間違っています。私はちょうど動的メモリ割り当てを使用します。 – john

答えて

6

for(int id=0; id<n; id++) { 
    Object ob = Object(id); 
    v.push_back(&ob); 
} 

あなたはn回を作成しているが、スタック上のインスタンスオブジェクト。すべての反復で、要素が作成および削除されます。

すべての新しい要素がスタック上に存在しないため、すべての要素がヒープ上に存在することに感謝します。デストラクタで

std::cout<<"Object ctor()\n"; 

と同じ:クラスObjectコンストラクタでにそのような何かを追加しよう

std::cout<<"Object dtor()\n"; 

あなたが@で書かれた「新しい」のtry理由でこれらのオブジェクトを作成したくない場合woolstar

+0

エラーを通知する+1 – Pat

3

はなしバージョンにはメモリリークが存在しないクラスBのオブジェクトに非常に奇妙な動作が発生することはありませんでした。プログラムがあなたのスコープをベクトルから離れると、配列も破壊されます。あなたの2番目の質問に:なぜオブジェクトをベクターに直接格納しないのですか?

vector<Object> v; 

for(int i = 0; i < n; i++) 
{ 
    Object obj = Object(i); 
    v.push_back(obj); 
} 
5

メモリリークに関するご質問は、これらのオブジェクトのライフサイクルとクリーンアップが心配だと思います。もともと私はshared_ptrラッパーを提案しましたが、C++ 11はunique_ptrを与え、C++ 14は不足したmake_uniqueを埋めました。だから我々が行うことができるすべてを持つ:あなたは完璧な転送および可変長テンプレートの素晴らしさに代わって作成

vector<unique_ptr<SuperObject>> v ; 

v.push_back(make_unique<Object>(...)) ; 

はいあなたには、いくつかのヒープ割り当てと一緒に暮らすために持ってしようとしています、 vがなくなるとすべてがクリーンアップされます。

誰かがブーストライブラリptr_containerを提案しましたが、それはあなたのプロジェクトにブーストを加えるだけでなく、将来のすべての読者に何を教えているのかを理解することです。ptr_containerこのループでは

+3

shared_ptrセマンティクスが必要な場合を除き、これをしないでください。 http://www.boost.org/doc/libs/1_55_0/libs/ptr_container/doc/ptr_container.htmlを使用してください。 – KitsuneYMG

関連する問題