std :: vectorの集約 リストの初期化は、移動がより適切な場合にコピーの初期化を実行することに気付きました。同時に、複数のemplace_backsが必要な処理を実行します。
テンプレート関数を書くというこの不完全な解決策しか思いつかなかったinit_emplace_vector
。ただし、明示的ではない単一値コンストラクターにのみ最適です。
template <typename T, typename... Args>
std::vector<T> init_emplace_vector(Args&&... args)
{
std::vector<T> vec;
vec.reserve(sizeof...(Args)); // by suggestion from user: eerorika
(vec.emplace_back(std::forward<Args>(args)), ...); // C++17
return vec;
}
質問
std :: vectorをできるだけ効率的に初期化するために、本当にemplace_backを使用する必要がありますか?
// an integer passed to large is actually the size of the resource
std::vector<large> v_init {
1000, // instance of class "large" is copied
1001, // copied
1002, // copied
};
std::vector<large> v_emplaced;
v_emplaced.emplace_back(1000); // moved
v_emplaced.emplace_back(1001); // moved
v_emplaced.emplace_back(1002); // moved
std::vector<large> v_init_emplace = init_emplace_vector<large>(
1000, // moved
1001, // moved
1002 // moved
);
出力
クラスlarge
はコピー/移動(以下の実装)に関する情報を生成するので、私のプログラムの出力は次のとおりです。
- initializer
large copy
large copy
large copy
- emplace_back
large move
large move
large move
- init_emplace_vector
large move
large move
large move
大規模クラスの実装
私の実装large
は、コピー/移動を警告する大きなリソースを保持する、単にコピー/移動可能なタイプです。
struct large
{
large(std::size_t size) : size(size), data(new int[size]) {}
large(const large& rhs) : size(rhs.size), data(new int[rhs.size])
{
std::copy(rhs.data, rhs.data + rhs.size, data);
std::puts("large copy");
}
large(large&& rhs) noexcept : size(rhs.size), data(rhs.data)
{
rhs.size = 0;
rhs.data = nullptr;
std::puts("large move");
}
large& operator=(large rhs) noexcept
{
std::swap(*this, rhs);
return *this;
}
~large() { delete[] data; }
int* data;
std::size_t size;
};
編集する
予約を使用すると、コピーや移動はありません。large::large(std::size_t)
コンストラクタのみが呼び出されます。本当の場所。
std :: vectorのコンストラクターは混乱を招く混乱したIMHOであり、もし私があなただったら、絶対にやらなくてはならないのであれば、その中に入るのは本当に避けたいでしょう。さらに、ベクターのコンテンツを事前に知っている場合(そうであるように思われます)-を検討してください
—
アインポクルム
std::array
。
operator=
ソースを破壊するには、非常に異例のことだと予期しない問題が発生する可能性があります。
init_emplace_vector
改善のvec.reserve(sizeof...(Args))
@alain
—
1
operator=
はソースを破壊しません。コピースワップイディオムです。
std::initializer_list
。