如何从C风格的数组初始化std :: vector?

Fra*_*ank 156 c++ arrays stl vector

std::vector从C风格的数组初始化a的最便宜的方法是什么?

示例:在下面的类中,我有一个vector,但由于外部限制,数据将作为C样式数组传递:

class Foo {
  std::vector<double> w_;
public:
  void set_data(double* w, int len){
   // how to cheaply initialize the std::vector?
}
Run Code Online (Sandbox Code Playgroud)

显然,我可以调用w_.resize()然后循环遍历元素,或者调用std::copy().有没有更好的方法?

Pav*_*aev 214

不要忘记您可以将指针视为迭代器:

w_.assign(w, w + len);
Run Code Online (Sandbox Code Playgroud)

  • 快速解决方案可以是std :: vector <double> w_(w,w + len); (33认同)
  • 这会将元素复制到新创建的 'w_' 存储;'w_.data' 不会指向 'w'。你仍然需要释放'w'。没有所有权转移 (4认同)
  • 这是一个实施质量问题.由于迭代有指定其类别标签,assign`的`的实现肯定是免费使用它们来优化; 至少在VC++中,它确实做到了这一点. (3认同)
  • 很快,当向量超出范围时,这会释放数组内存吗? (2认同)

Mar*_*k B 37

您使用单词initialize,因此不清楚这是一次性分配还是可能多次发生.

如果您只需要一次初始化,可以将它放在构造函数中并使用两个迭代器向量构造函数:

Foo::Foo(double* w, int len) : w_(w, w + len) { }
Run Code Online (Sandbox Code Playgroud)

否则使用如前所述的assign:

void set_data(double* w, int len)
{
    w_.assign(w, w + len);
}
Run Code Online (Sandbox Code Playgroud)


Mug*_*rel 11

好吧,Pavel很接近,但是甚至有一个更简单和优雅的解决方案来从ac样式数组初始化顺序容器.

在你的情况下:

w_ (array, std::end(array))
Run Code Online (Sandbox Code Playgroud)
  • 数组会给我们一个指向数组开头的指针(没有抓住它的名字),
  • std :: end(array)将为我们提供一个到数组末尾的迭代器.

  • 请注意,这只适用于你有一个真正的`数组`(通常意味着你是从全局或本地(在当前函数中声明)数组中复制).在OP的情况下,他正在接收一个指针和一个长度,并且因为它不是模板的长度,它们不能改变为接收指向大小的数组或任何东西的指针,所以`std :: end`将不起作用. (12认同)
  • 更独立的版本是: w_ (std::begin(array), std::end(array)); (将来您可以将 C 数组更改为 C++ 容器)。 (2认同)
  • `vector` 不会重载 `operator()`,因此不会编译。在指针上调用 `std::end` 也没有用(问题要求从指针和单独的长度变量分配一个向量)。显示更多关于您尝试建议的内容的上下文会改善您的答案 (2认同)

Aar*_*aid 10

您可以自动"学习"阵列的大小:

template<typename T, size_t N>
void set_data(const T (&w)[N]){
    w_.assign(w, w+N);
}
Run Code Online (Sandbox Code Playgroud)

希望您可以将界面更改为set_data,如上所示.它仍然接受C风格的数组作为它的第一个参数.它恰好通过引用来接受它.


这个怎么运作

[更新:请参阅此处以获得有关学习规模的更全面的讨论]

这是一个更通用的解决方案:

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);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为数组作为引用到数组传递.在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);
}
Run Code Online (Sandbox Code Playgroud)


eus*_*iro 7

快速通用答案:

std::vector<double> vec(carray,carray+carray_size); 
Run Code Online (Sandbox Code Playgroud)

或具体问题:

std::vector<double> w_(w,w+len); 
Run Code Online (Sandbox Code Playgroud)

基于以上不要忘记您可以将指针视为迭代器