Farzad
Farzad

Reputation: 3438

Is it possible that a pointer gets owned by a vector without any data copy?

If I have a C type raw pointer, is it possible to create a std::vector from the same type that owns the pointer's data without any data copy (only moving)? What motivates me for asking this question is the existence of data() member function for std::vector which means vector's elements are residing somewhere in the memory consecutively.

Edit: I have to add that the hope I had was also intensified by the existence of functions like std::make_shared.

Upvotes: 4

Views: 924

Answers (3)

5gon12eder
5gon12eder

Reputation: 25439

I don't think that this is directly possible, although you're not the first one to miss this feature. It is even more painful with std::string which doesn't have a non-const data member. Hopefully, this will change in C++17.

If you are allocating the buffer yourself, there is a solution, though. Just use a std::vector up-front. For example, assume you have the following C-style function,

extern void
fill_in_the_numbers(double * buffer, std::size_t count);

then you can do the following.

std::vector<double>
get_the_numbers_1st(const std::size_t n)
{
  auto numbers = std::vector<double> (n);
  fill_in_the_numbers(numbers.data(), numbers.size());
  return numbers;
}

Alternatively, if you're not so lucky and your C-style function insists in allocating the memory itself,

extern double *
allocate_the_buffer_and_fill_in_the_numbers(std::size_t n);

you could resort to a std::unique_ptr, which is sadly inferior.

std::unique_ptr<double[], void (*)(void *)>
get_the_numbers_2nd(const std::size_t n)
{
  return {
    allocate_the_buffer_and_fill_in_the_numbers(n),
    &std::free
  };
}

Upvotes: 3

WhiZTiM
WhiZTiM

Reputation: 21576

Yes, provided that you've created and populated the vector before getting the pointers and that you will not

  1. erase any element
  2. you will not add new elements when vec.size() == vec.capacity() - 1 ,,, doing so will change the address of the elements

Example

#include <iostream>

void fill_my_vector<std::vector<double>& vec){
    for(int i=0; i<300; i++){
        vec.push_back(i);
    }
}

void do_something(double* d, int size)
{ /* ..... */ }

int main(){
    std::vector<double> vec;
    fill_my_vector(vec);
    //You hereby promise to follow the contract conditions, then you are safe doing this

    double* ptr;
    int ptr_len = vec.size();
    ptr = &vec[0];

    //call do_something
    do_something(ptr, ptr_len);

    //ptr will be alive until this function scope exits
}

EDIT

If you mean managing the data from an already created array, you can't... vector manages its own array... It cannot take ownership of an array that wasn't created by its class (vector).

Upvotes: 0

kmdreko
kmdreko

Reputation: 60367

No, std::vector is not designed to be able to assume/utilize a pre-existing array for its internal storage.

Upvotes: 2

Related Questions