web-dev-qa-db-ja.com

C ++、ベクターへのコピーセット

std::setstd::vectorにコピーする必要があります。

std::set <double> input;
input.insert(5);
input.insert(6);

std::vector <double> output;
std::copy(input.begin(), input.end(), output.begin()); //Error: Vector iterator not dereferencable

問題はどこにありますか?

127
CrocodileDundee

back_inserterを使用する必要があります:

std::copy(input.begin(), input.end(), std::back_inserter(output));

std::copyは、挿入先のコンテナに要素を追加しません。できません。コンテナへのイテレータのみがあります。このため、出力反復子をstd::copyに直接渡す場合、少なくとも入力範囲を保持するのに十分な大きさの範囲を指すようにする必要があります。

std::back_inserterは、各要素のコンテナでPush_backを呼び出す出力イテレータを作成し、各要素がコンテナに挿入されるようにします。または、コピーする範囲を保持するのに十分な数の要素をstd::vectorに作成することもできます。

std::vector<double> output(input.size());
std::copy(input.begin(), input.end(), output.begin());

または、std::vector範囲コンストラクターを使用できます。

std::vector<double> output(input.begin(), input.end()); 
201
James McNellis

イテレータを受け取るベクトルのコンストラクタを使用するだけです。

std::set<T> s;

//...

std::vector v( s.begin(), s.end() );

Vのsのコンテンツだけが必要であり、vにデータをコピーする前にvに何もないと仮定します。

113
Jacob

vector::assignを使用する別の代替手段を次に示します。

theVector.assign(theSet.begin(), theSet.end());
34
TeddyC

セットの内容を保持するのに十分なスペースがベクターオブジェクトに予約されていません。

std::vector<double> output(input.size());
std::copy(input.begin(), input.end(), output.begin());
23
Marlon

std::copyを使用して空のコンテナに挿入することはできません。そのためには、次のようなinsert_iteratorを使用する必要があります。

std::set<double> input;
input.insert(5);
input.insert(6);

std::vector<double> output;
std::copy(input.begin(), input.end(), inserter(output, output.begin())); 
1
Bradley Swain

最も効率的な方法は、要素を事前に割り当ててから配置することだと思います。

template <typename T>
std::vector<T> VectorFromSet(const std::set<T>& from)
{
    std::vector<T> to;
    to.reserve(from.size());

    for (auto const& value : from)
        to.emplace_back(value);

    return to;
}

この方法では、最初にデフォルトのコンストラクターを呼び出してから、上記の他のソリューションの代入演算子をコピーするのではなく、すべての要素に対してコピーコンストラクターのみを呼び出します。以下に詳細を説明します。

  1. back_inserterを使用できますが、ベクターでPush_back()を呼び出します( https://en.cppreference.com/w/cpp/iterator/back_insert_iterator =)。 emplace_back()は、Push_back()の使用時に一時的な作成を回避するため、より効率的です。簡単に構築される型では問題になりませんが、非自明に構築される型(std :: stringなど)のパフォーマンスに影響します。

  2. すべての要素がデフォルトで構築される(何もしない)サイズ引数でベクトルを構築することを避ける必要があります。たとえば、std :: copy()を使用したソリューションと同様です。

  3. そして、最後に、vector :: assign()メソッドまたはイテレーター範囲をとるコンストラクターは、std :: distance()(要素の数を知るために) )set反復子。これは、セットがバイナリ検索ツリーのデータ構造であり、ランダムアクセスイテレータを実装していないため、すべてのset要素で不要な追加の反復が発生します。

お役に立てば幸いです。

1
dshvets1