C++,复制集到向量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5034211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:14:01  来源:igfitidea点击:

C++, copy set to vector

c++copystdvectorstdset

提问by CrocodileDundee

I need to copy std::setto std::vector:

我需要复制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

Where is the problem?

问题出在哪儿?

回答by James McNellis

You need to use a back_inserter:

你需要使用一个back_inserter

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

std::copydoesn't add elements to the container into which you are inserting: it can't; it only has an iterator into the container. Because of this, if you pass an output iterator directly to std::copy, you must make sure it points to a range that is at least large enough to hold the input range.

std::copy不会向您要插入的容器添加元素:它不能;它只有一个进入容器的迭代器。因此,如果将输出迭代器直接传递给std::copy,则必须确保它指向的范围至少足以容纳输入范围。

std::back_insertercreates an output iterator that calls push_backon a container for each element, so each element is inserted into the container. Alternatively, you could have created a sufficient number of elements in the std::vectorto hold the range being copied:

std::back_inserter创建一个输出迭代器,push_back为每个元素调用一个容器,因此每个元素都被插入到容器中。或者,您可以在 中创建足够数量的元素std::vector来保存被复制的范围:

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

Or, you could use the std::vectorrange constructor:

或者,您可以使用std::vector范围构造函数:

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

回答by Jacob

Just use the constructor for the vector that takes iterators:

只需使用带有迭代器的向量的构造函数:

std::set<T> s;

//...

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

Assumes you just want the content of s in v, and there's nothing in v prior to copying the data to it.

假设您只想要 v 中 s 的内容,并且在将数据复制到 v 之前 v 中没有任何内容。

回答by TeddyC

here's another alternative using vector::assign:

这是使用的另一种选择vector::assign

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

回答by Marlon

You haven't reserved enough space in your vector object to hold the contents of your set.

您没有在矢量对象中保留足够的空间来保存集合的内容。

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

回答by dshvets1

I think the most efficient way is to preallocate and then emplace elements:

我认为最有效的方法是预先分配然后放置元素:

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;
}

That way we will only invoke copy constructor for every element as opposed to calling default constructor first and then copy assignment operator for other solutions listed above. More clarifications below.

这样我们只会为每个元素调用复制构造函数,而不是先调用默认构造函数,然后为上面列出的其他解决方案复制赋值运算符。更多说明如下。

  1. back_insertermay be used but it will invoke push_back() on the vector (https://en.cppreference.com/w/cpp/iterator/back_insert_iterator). emplace_back()is more efficient because it avoids creating a temporary when using push_back(). It is not a problem with trivially constructed types but will be a performance implication for non-trivially constructed types (e.g. std::string).

  2. We need to avoid constructing a vector with the size argument which causes all elements default constructed (for nothing). Like with solution using std::copy(), for instance.

  3. And, finally, vector::assign()method or the constructor taking the iterator range are not good options because they will invoke std::distance() (to know number of elements) on setiterators. This will cause unwanted additional iteration through the all setelements because the set is Binary Search Tree data structure and it does not implement random access iterators.

  1. 可以使用back_inserter但它会在向量上调用 push_back() ( https://en.cppreference.com/w/cpp/iterator/back_insert_iterator)。 emplace_back()更有效,因为它避免在使用push_back()时创建临时文件。这对简单构造的类型不是问题,但对非普通构造的类型(例如 std::string)会产生性能影响。

  2. 我们需要避免使用 size 参数构造向量,这会导致所有元素默认构造(无用)。例如,就像使用std::copy() 的解决方案一样。

  3. 最后,vector::assign()方法或采用迭代器范围的构造函数不是好的选择,因为它们会在集合迭代器上调用 std::distance() (以了解元素的数量)。这将导致对所有集合元素进行不必要的额外迭代,因为该集合是二叉搜索树数据结构,并且它没有实现随机访问迭代器。

Hope that helps.

希望有帮助。

回答by Bradley Swain

std::copycannot be used to insert into an empty container. To do that, you need to use an insert_iterator like so:

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()));