いくつかのレガシーコードを使用してプロジェクトで作業しているときに、この関数を見つけました。
std::vector<std::string> Object::getTypes(){
static std::string types [] = {"type1","type2", "type3"};
return std::vector<std::string> (types , types +2);
}
私はおそらくこれを次のように書いたでしょう:
std::vector<std::string> Object::getTypes(){
std::vector<std::string> types;
types.Push_back("type1");
types.Push_back("type2");
types.Push_back("type3");
return types;
}
これは単なるスタイルの選択ですか、それとも私が欠けているものがありますか?どんな助けでも大歓迎です。これが基本的すぎる場合は申し訳ありません。
pdate:実際には、同じメソッドをオーバーライドするさまざまなクラスが何らかの方法でそれを実行することがわかったため、さらにあいまいになります。私はそれらをすべて同じにしますが、もしあれば、より良いアプローチを好みます。
編集
上記のレガシーコードは、配列の最初の2つの要素のみでベクトルを初期化するため、正しくないことに注意してください。ただし、このエラーはコメントで説明されているため、保持する必要があります。
正しい初期化は次のようになっているはずです。
...
return std::vector<std::string> (types, types + 3);
...
最初の例の配列types
は静的として宣言されています。これは、メモリ内に1回だけ存在することを意味します。したがって、何を返すかについては3つのオプションがあり、それらは静的メモリに存在します。次に、返すベクトルを作成するときに、配列の最初と最後をイテレータとして渡すことで、そのメモリを1回のショットで割り当てることができます。
このようにすることで、Push_back
を連続して呼び出す必要がなくなります。つまり、ベクターはメモリの内部ブロックを再割り当てする必要がありません。
また、ベクトルがreturn呼び出しの一部として構築される場合、古いコンパイラーは 戻り値の最適化 を実行するのが簡単になります。
C++ 11対応のコンパイラとライブラリがある場合は、初期化子リストを返すだけで十分です。
std::vector<std::string> Object::getTypes(){
return {"type1","type2", "type3"};
}
見つけたコードの方が効率的です(types[]
は1回だけ割り当てられ、Push_back
再割り当てが発生する可能性があります)。ただし、違いはごくわずかであり、(比較的大きな)ループでgetTypes
を呼び出さない限り、まったく問題にはなりません(大きなループで呼び出したとしても、おそらくそれほど重要ではありません)。 。
そのため、具体的なパフォーマンスの問題が発生しない限り、スタイルの選択になります。
基本的にそれはスタイルの選択です。私はおそらくもっと好きなことをするでしょう
std::vector<std::string> Object::getTypes(){
static std::string types [] = {"type1","type2", "type3"};
return std::vector<std::string> (types,
types + (sizeof(types)/sizeof(std::string)) );
}
これにより、次の行のカウントを更新することを忘れずに、タイプ内のアイテムの数を変更できます。
このスタイルの初期化をイテレーター(およびC++ 11の統一された初期化リストと初期化リスト)で使用するのが好きな理由の1つは、データをコードから分離するのに役立つためです。
繰り返しPush_back
私は必死にそれをリファクタリングする必要があるので、多くの場合気分が悪くなります。また、実際にコンテナをデータで初期化する必要がある場合は、データを生成するコードではなく、データのリストを表示する必要があります。元のバージョンで見つけた方法は、その原則によりよく一致します。