如何使用 C 样式数组分配 std::vector?

发布于 2024-08-24 18:08:24 字数 380 浏览 5 评论 0原文

从 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()。还有更好的方法吗?

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

喜爱皱眉﹌ 2024-08-31 18:08:24

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

w_.assign(w, w + len);

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

w_.assign(w, w + len);
枕梦 2024-08-31 18:08:24

您使用了“初始化”一词,因此不清楚这是一次性分配还是可以多次发生。

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

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

否则按照前面的建议使用分配:

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

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);
}
云柯 2024-08-31 18:08:24

快速通用答案:

std::vector<double> vec(carray,carray+carray_size); 

或特定问题:

std::vector<double> w_(w,w+len); 

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

The quick generic answer:

std::vector<double> vec(carray,carray+carray_size); 

or question specific:

std::vector<double> w_(w,w+len); 

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

南渊 2024-08-31 18:08:24

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

在你的情况下:

w_ (array, std::end(array))
  • array 将为我们提供一个指向数组开头的指针(没有捕获它的名称),
  • std::end(array) 将为我们提供一个指向数组末尾的迭代器。

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

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.
把回忆走一遍 2024-08-31 18:08:24

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

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

希望您可以将接口更改为上面的 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);
}

这是有效的,因为数组被作为引用传递给-一个数组。在 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);
}

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.


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.

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.

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);
}
花海 2024-08-31 18:08:24

std::vector::assign 是可行的方法,因为它代码很少。但实际上它是如何运作的呢?不是先调整大小然后复制吗?在我使用的 STL 的 MS 实现中,它正是这样做的。

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

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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文