3

I am working with a function which requires me to pass in an C-style array so it can be filled with data. However, the resulting array must be converted to a vector so it can be passed to another function that needs it. The vector constraint is hard, there's no getting around it. I could conceivably rework the other function so that it takes a vector, but I'd prefer not to if it can be done efficiently otherwise. Specifically, I would like there to be no copying of the data from the array to the vector if possible. As a minimal example, take the following program:

#include <iostream>
#include <algorithm>
#include <vector>
#include <chrono>

using namespace std::chrono;

static uint LENGTH = 10000000;


uint now() {
    return duration_cast<microseconds>
            (system_clock::now().time_since_epoch()).count();
}

void put_data_in_array(char *data) {
    std::cout << now() << " filling array\n";
    for (uint i = 0; i < LENGTH; i++) {
        data[i] = i;
    }
    std::cout << now() << " filled array\n";
}

int main () {
    std::cout << now() << " making array\n";
    char *array = new char[LENGTH];
    std::cout << now() << " made array\n";
    put_data_in_array(array);
    std::cout << now() << " function returned\n";
    std::vector<char> v;
    std::move(array, array + LENGTH, std::back_inserter(v));
    std::cout << now() << " switched to vector\n";
  return 0;
}

which produces the following output:

1970760826 making array
1970760926 made array
1970760927 filling array
1970774417 filled array
1970774421 function returned
1970879936 switched to vector

meaning:

100 µs to allocate memory for the array
13490 µs to fill the array
105515 µs to move the array to a vector

Ideally, I would like the time to move the array to a vector to be very small. If possible I'd like to tell the vector to take ownership of the existing array. However, if the time to transfer it to a vector can be close (less than twice) the time it takes to fill the array, I will be happy.

Thanks for any help you can give.

Edit:

Thanks for all the quick feedback! As it turns out, passing v.data() is probably the best way to accomplish what I'm looking for. I really don't care about array at all, I just knew I had to pass an array to the function.

Community
  • 1
  • 1
Jon McClung
  • 1,619
  • 20
  • 28
  • 2
    You need to `reserve` the space in `v`. – NathanOliver Aug 02 '18 at 16:51
  • @NathanOliver I didn't even think about how many times it would have to grow. Thanks! – Jon McClung Aug 02 '18 at 16:53
  • I really need to get out more. Apparently the [`std::move`](https://en.cppreference.com/w/cpp/algorithm/move) gnomes have been busy. Damn RL interfering with my standard browsing time *again*. – WhozCraig Aug 02 '18 at 16:54
  • 3
    Also, consider using `vector` from the start. You can pass its `.data()` to `put_data_in_array`. – Dan M. Aug 02 '18 at 16:56
  • @DanM. your advice is well taken. I kept thinking there ought to be some way to do something like that! – Jon McClung Aug 02 '18 at 16:59
  • Can you elaborate why you want to avoid writing the data directly into a `std::vector`? Other than that I think the `.data()` idea is definitely the right choice. Dan should probably post that as an answer (since the other answer is stuck with your XY problem). – Max Langhof Aug 02 '18 at 16:59
  • 2
    @WhozCraig sorry, I'm out of the loop. What is a "std::move gnome"? Also, "RL"? – Jon McClung Aug 02 '18 at 16:59
  • @JonMcClung "RL" = "real life". For "`std::move` gnomes" I feel there have been a few deleted comments were referenced there. Or a comment in the wrong question. – Max Langhof Aug 02 '18 at 17:01
  • @JonMcClung The phrase "the gnomes have been busy" is in reference to the fictitious garden gnomes that would care and tend for your gardens whilst you were sleeping, or otherwise away. One would leave for the day, returning to find their garden tended by the little gnomes. In modern day, people adorn their gardens and planters with ceramic statues depicting them (some of which can become incredibly rare and valuable over time). Anyway, it's a phrase used when one isn't paying attention, then returns to find undiscovered things. Sorry for the confusion. – WhozCraig Aug 02 '18 at 17:05

1 Answers1

5

There's no way to avoid copying the array to the vector.

The most efficient way should be to use the vector constructor to do the copy. Use two pointers which will act like begin/end iterators.

std::vector<int64_t> v(array, array + LENGTH);
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622