如何初始化std:: C-style数组中的向量?

时间:2021-08-25 22:25:02

What is the cheapest way to initialize a std::vector from a C-style array?

初始化来自c样式数组的std::vector的最便宜方法是什么?

Example: In the following class, I have a vector, but due to outside restrictions, the data will be passed in as C-style array:

例:在下面的类中,我有一个向量,但由于外部限制,数据将以c样式数组的形式传递:

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

Obviously, I can call w_.resize() and then loop over the elements, or call std::copy(). Are there any better methods?

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

5 个解决方案

#1


185  

Don't forget that you can treat pointers as iterators:

不要忘记你可以把指针当作迭代器:

w_.assign(w, w + len);

#2


31  

You use the word initialize so it's unclear if this is one-time assignment or can happen multiple times.

你使用“初始化”这个词,所以不清楚这是一次性的赋值,还是可能发生多次。

If you just need a one time initialization, you can put it in the constructor and use the two iterator vector constructor:

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

Foo::Foo(double* w, int len) : w_(w, w + len) { }

Otherwise use assign as previously suggested:

如前所述,使用分配:

void set_data(double* w, int len)
{
    w_.assign(w, w + len);
}

#3


10  

Well, Pavel was close, but there's even a more simple and elegant solution to initialize a sequential container from a c style array.

好吧,Pavel很接近,但是还有一个更简单、更优雅的解决方案来从c样式数组初始化一个顺序容器。

In your case:

在你的例子:

w_ (array, std::end(array))
  • array will get us a pointer to the beginning of the array (didn't catch it's name),
  • 数组会给我们一个指向数组开头的指针(没有记住它的名字),
  • std::end(array) will get us an iterator to the end of the array.
  • std::end(数组)将会得到一个迭代器到数组的末尾。

#4


8  

You can 'learn' the size of the array automatically:

您可以自动“了解”数组的大小:

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

Hopefully, you can change the interface to set_data as above. It still accepts a C-style array as its first argument. It just happens to take it by reference.

希望您可以将接口更改为set_data。它仍然接受c样式的数组作为它的第一个参数。只是碰巧引用了它。


How it works

它是如何工作的

[ Update: See here for a more comprehensive discussion on learning the size ]

[更新:关于规模学习的更全面的讨论见这里]

Here is a more general solution:

下面是一个更普遍的解决方案:

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

This works because the array is being passed as a reference-to-an-array. In C/C++, you cannot pass an array as a function, instead it will decay to a pointer and you lose the size. But in C++, you can pass a reference to the array.

这之所以有效,是因为数组作为一个指向数组的引用被传递。在C/ c++中,不能将数组作为函数传递,而是将其衰减为指针,从而丢失了大小。但是在c++中,可以将引用传递给数组。

Passing an array by reference requires the types to match up exactly. The size of an array is part of its type. This means we can use the template parameter N to learn the size for us.

通过引用传递数组要求类型完全匹配。数组的大小是其类型的一部分。这意味着我们可以使用模板参数N来了解我们的大小。

It might be even simpler to have this function which returns a vector. With appropriate compiler optimizations in effect, this should be faster than it looks.

让这个函数返回一个向量可能更简单。通过适当的编译器优化,这应该比看上去的要快。

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

#5


1  

std::vector<double>::assign is the way to go, because it's little code. But how does it work, actually? Doesnt't it resize and then copy? In MS implementation of STL I am using it does exactly so.

向量 ::assign是方法,因为它是小代码。但是它是如何工作的呢?它不是调整大小然后复制吗?在STL的MS实现中,我就是这么用的。

I'm afraid there's no faster way to implement (re)initializing your std::vector.

恐怕没有更快的方法来实现(重新)初始化std::vector。

#1


185  

Don't forget that you can treat pointers as iterators:

不要忘记你可以把指针当作迭代器:

w_.assign(w, w + len);

#2


31  

You use the word initialize so it's unclear if this is one-time assignment or can happen multiple times.

你使用“初始化”这个词,所以不清楚这是一次性的赋值,还是可能发生多次。

If you just need a one time initialization, you can put it in the constructor and use the two iterator vector constructor:

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

Foo::Foo(double* w, int len) : w_(w, w + len) { }

Otherwise use assign as previously suggested:

如前所述,使用分配:

void set_data(double* w, int len)
{
    w_.assign(w, w + len);
}

#3


10  

Well, Pavel was close, but there's even a more simple and elegant solution to initialize a sequential container from a c style array.

好吧,Pavel很接近,但是还有一个更简单、更优雅的解决方案来从c样式数组初始化一个顺序容器。

In your case:

在你的例子:

w_ (array, std::end(array))
  • array will get us a pointer to the beginning of the array (didn't catch it's name),
  • 数组会给我们一个指向数组开头的指针(没有记住它的名字),
  • std::end(array) will get us an iterator to the end of the array.
  • std::end(数组)将会得到一个迭代器到数组的末尾。

#4


8  

You can 'learn' the size of the array automatically:

您可以自动“了解”数组的大小:

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

Hopefully, you can change the interface to set_data as above. It still accepts a C-style array as its first argument. It just happens to take it by reference.

希望您可以将接口更改为set_data。它仍然接受c样式的数组作为它的第一个参数。只是碰巧引用了它。


How it works

它是如何工作的

[ Update: See here for a more comprehensive discussion on learning the size ]

[更新:关于规模学习的更全面的讨论见这里]

Here is a more general solution:

下面是一个更普遍的解决方案:

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

This works because the array is being passed as a reference-to-an-array. In C/C++, you cannot pass an array as a function, instead it will decay to a pointer and you lose the size. But in C++, you can pass a reference to the array.

这之所以有效,是因为数组作为一个指向数组的引用被传递。在C/ c++中,不能将数组作为函数传递,而是将其衰减为指针,从而丢失了大小。但是在c++中,可以将引用传递给数组。

Passing an array by reference requires the types to match up exactly. The size of an array is part of its type. This means we can use the template parameter N to learn the size for us.

通过引用传递数组要求类型完全匹配。数组的大小是其类型的一部分。这意味着我们可以使用模板参数N来了解我们的大小。

It might be even simpler to have this function which returns a vector. With appropriate compiler optimizations in effect, this should be faster than it looks.

让这个函数返回一个向量可能更简单。通过适当的编译器优化,这应该比看上去的要快。

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

#5


1  

std::vector<double>::assign is the way to go, because it's little code. But how does it work, actually? Doesnt't it resize and then copy? In MS implementation of STL I am using it does exactly so.

向量 ::assign是方法,因为它是小代码。但是它是如何工作的呢?它不是调整大小然后复制吗?在STL的MS实现中,我就是这么用的。

I'm afraid there's no faster way to implement (re)initializing your std::vector.

恐怕没有更快的方法来实现(重新)初始化std::vector。