从 C 样式数组初始化 std::vector
最便宜的方法是什么?
示例:在下面的类中,我有一个 vector
,但由于外部限制,数据将作为 C 样式数组传入:
class Foo {
std::vector<double> w_;
public:
void set_data(double* w, int len){
// how to cheaply initialize the std::vector?
}
显然,我可以调用 w_.resize()
然后循环遍历元素,或者调用 std::copy()
。有没有更好的方法?
不要忘记您可以将指针视为迭代器:
w_.assign(w, w + len);
您使用初始化这个词,因此不清楚这是一次性分配还是可以多次发生。
如果你只需要一次初始化,你可以把它放在构造函数中,并使用两个迭代器向量构造函数:
Foo::Foo(double* w, int len) : w_(w, w + len) { }
否则使用前面建议的分配:
void set_data(double* w, int len)
{
w_.assign(w, w + len);
}
好吧,Pavel 很接近,但是还有一个更简单和优雅的解决方案来从 ac 样式数组初始化一个顺序容器。
在你的情况下:
w_ (array, std::end(array))
array 会给我们一个指向数组开头的指针(没有抓住它的名字),
std::end(array) 将为我们提供一个指向数组末尾的迭代器。
array
时才有效(这通常意味着您正在从全局或本地(在当前函数中声明)数组复制)。在 OP 的情况下,他正在接收一个指针和一个长度,并且因为它没有在长度上进行模板化,所以它们不能更改为接收指向大小数组或任何东西的指针,所以 std::end
将不起作用。
vector
不会重载 operator()
,因此无法编译。 std::end
在指针上调用也是没有用的(问题要求从指针和单独的长度变量分配一个向量)。这将改善您的答案,以显示有关您要建议的内容的更多上下文
您可以自动“学习”数组的大小:
template<typename T, size_t N>
void set_data(const T (&w)[N]){
w_.assign(w, w+N);
}
希望您可以如上所述将接口更改为 set_data。它仍然接受一个 C 风格的数组作为它的第一个参数。它只是碰巧引用它。
这个怎么运作
更新:有关了解大小的更全面讨论,请参阅 here]
这是一个更通用的解决方案:
template<typename T, size_t N>
void copy_from_array(vector<T> &target_vector, const T (&source_array)[N]) {
target_vector.assign(source_array, source_array+N);
}
这是有效的,因为数组是作为对数组的引用传递的。在 C/C++ 中,您不能将数组作为函数传递,而是会衰减为指针并且您会丢失大小。但在 C++ 中,您可以传递对数组的引用。
通过引用传递数组需要类型完全匹配。数组的大小是其类型的一部分。这意味着我们可以使用模板参数 N 来为我们学习大小。
让这个函数返回一个向量可能更简单。通过适当的编译器优化,这应该比看起来要快。
template<typename T, size_t N>
vector<T> convert_array_to_vector(const T (&source_array)[N]) {
return vector<T>(source_array, source_array+N);
}
return { begin(source_array), end(source_array) };
也是可能的
快速的通用答案:
std::vector<double> vec(carray,carray+carray_size);
或具体问题:
std::vector<double> w_(w,w+len);
基于 above:不要忘记您可以将指针视为迭代器
std::vector<double>::assign
是要走的路,因为它是小代码。但实际上它是如何工作的?它不会调整大小然后复制吗?在 STL 的 MS 实现中,我正在使用它。
恐怕没有没有更快的方法来实现(重新)初始化您的 std::vector
。
不定期副业成功案例分享
assign
的实现当然可以免费使用它们进行优化;至少在 VC++ 中,它确实做到了这一点。v.end()
是一个迭代器,在类似的情况下用向量指向结束后的一个)。如果你确实得到了一个断言,那么其他地方就有问题了。