views:

338

answers:

4

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?

+15  A: 

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

w_.assign(w, w + len);
Pavel Minaev
Is there a performance difference between `std::copy(w, w + len, w_.begin())` and your `assign` solution?
Oh, I guess the difference is that `std::copy` will not resize the array.
I don't know if *assign* is smart enough to compute how much *w* is distant from *w+len* (a generic iterator AFAIK does not provide a quick way to do this), so you may enhance a little the performances putting a w_.reserve(len) before that statement; in the worst case you gain nothing. In this way it should have more or less the performance of resize+copy.
Matteo Italia
It's a quality of implementation issue. Since iterators have tags that specify their categories, an implementation of `assign` is certainly free to use them to optimize; at least in VC++, it does indeed do just that.
Pavel Minaev
+3  A: 

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);
}
Mark B
In my case, the assignment will happen repeatedly.
+1  A: 

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.

Janusz Lenar