2016-04-01 1 views
2

Если у меня есть необработанный указатель типа C, можно ли создать std::vector того же типа, который владеет данными указателя без каких-либо копий данных (только перемещение)? Меня мотивирует вопрос о существовании функции-члена data() для std::vector, что означает, что элементы вектора находятся где-то в памяти последовательно.Возможно ли, что указатель попадает под вектор без каких-либо копий данных?

Редактировать: Я должен добавить, что надежда у меня была также усилена существованием таких функций, как std::make_shared.

+0

Да, но бойтесь, что вектор будет изменен и будет аннулирован ваш указатель. Если вектор никогда не изменяет размер, и вы можете это гарантировать, вы в безопасности. – user4581301

+0

Вы выделяете буфер? Тогда вы можете позволить этому вектору сделать это. В противном случае я не знаю, как это может быть достигнуто. – 5gon12eder

+0

@ user4581301 вы можете передать право собственности на уже существующий массив на вектор? это новости для меня – vu1p3n0x

ответ

2

Я не думаю, что это возможно, хотя вы не первый, кто пропустил эту функцию. Это еще более болезненно с std::string, который не имеет члена constdata. Надеюсь, это изменится на C++ 17.

Если вы сами выделяете буфер, есть решение. Просто используйте переднюю панель std::vector. Например, предположим, что у вас есть следующая функция C-стиля,

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

то вы можете сделать следующее.

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

В качестве альтернативы, если вы не так повезло, и ваша функция C-стиль настаивает на выделении саму память,

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

можно прибегнуть к std::unique_ptr, который, к сожалению, хуже.

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

No, std::vector не предназначен для использования/использования ранее существовавшего массива для его внутреннего хранилища.

0

Да, при условии, что у Вас есть созданы и заполнены вектор перед тем, как указатели, и что вы не будете

  1. Стирание любой элемент
  2. вы не добавлять новые элементы, когда vec.size() == vec.capacity() - 1 ,,, делать это будет изменить адрес элементов

Пример

#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

Если вы имеете в виду управление данными из уже созданного массива, вы не можете ... вектор управляет своим собственным массив ... Он не может взять на себя ответственность массива, который не был создан по его классу (вектору).

+0

Если да, то теперь мой вопрос: как? – Farzad

+0

Хорошо, позвольте мне изменить свой ответ на «как» – WhiZTiM

+0

Друг, мы оба, кажется, неправильно поняли вопрос. У @Farzad, похоже, есть заранее выделенный пул памяти, который он хочет управлять с помощью вектора, а не использовать вектор как пул памяти. – user4581301