std::vectorでハマった。
今日はC++で作業していたのですが、std::vectorでハマりました。
最初、次のようなコードを書いていました。(イメージです)
struct SomeStruct { int number; float array[2]; }; void function(std::vector<SomeStruct> &struct_list) { for (int i = 0; i < N; i++) { SomeStruct some_struct; // SomeStructを作って some_struct.number = i; // 値をいろいろ入れて some_struct.array[0] = (float)i / N; some_struct.array[1] = (float)N / (i + 1); struct_list.push_back(some_struct); // vectorに入れる } }
しかし、これではstruct_listの内容がどうもおかしいということに気付きました。
なんというか、SomeStruct::arrayの中身が激しく壊れています。
なんだこれ、としばらく考えたあと、ちょっと検証を行って分かった事実が
SomeStructデストラクタが呼ばれているということでした。
よくよく考えてみればそれは当たり前で、ループ内のsome_structの寿命はループブロックの終わりまでです。
デストラクタが呼ばれるのも当然です。
当たり前のことでも、JavaとかC#とかの「基本的に参照で確保して、GCで回収」な言語を使っているとウッカリ忘れがちですね。
注意したいなと思った日でした。
あ、今回どのように修正したかというと、このように修正しました。
たぶんもっとスマートな方法があると思いますので、もしご存知でしたら教えていただけると幸いです。
(それこそスマートポインタの出番でしょうか?)
// ポインタを渡すようにした // 解放は呼び出し側が責任をもって行う必要がある void function(std::vector<SomeStruct*> &struct_list) { for (int i = 0; i < N; i++) { SomeStruct *some_struct = new SomeStruct(); some_struct->number = i; some_struct->array[0] = (float)i / N; some_struct->array[1] = (float)N / (i + 1); struct_list.push_back(some_struct); } }