как передать право собственности с c ++ std :: vector <char>на указатель char * - PullRequest
2 голосов
/ 27 февраля 2020

Я столкнулся с ситуацией, когда я получил std::vector<char> вывод данных из сторонней библиотеки, это данные очень большой длины, и затем мне нужно преобразовать их в pybind11::array объект, я не хочу выделить память и сделать memcpy, это вообще не эффективно.

Теперь я знаю, что могу получить адрес буфера std::vector<char>, но я не знаю, как освободить владение вектором, чтобы буфер не освобождался при разрушении векторного объекта, интересно, есть ли способ достичь этого.

Я написал тестовый код ниже для проверки, но он не прошел

#include<vector>
#include<iostream>
int *got_vec(int len){// the len in actually scene is decided by the thirdparty lib

  std::vector<int> vec;
  for(int i =0;i<len;i++){
    vec.push_back(i);
  }
  int *p_vec = &vec[0];
  std::move(vec);
  return p_vec;
}

int main(int argc,const char **argv){
  int len=atoi(argv[1]);

  std::cout<<"will go allocate memory size:"<<len<<", before allocation"<<std::endl; 

  int *p_vec = got_vec(len);
  std::cout<<"after allocation, go to print value"<<std::endl; 
  for(int i = 0; i < len;i++)
   std::cout<<p_vec[i]<<",";
  std::cout<<std::endl;

  delete p_vec;
  std::cout<<"deleted"<<std::endl;
}

Программа упала при std::cout<<p_vec[i]<<",";

Ответы [ 4 ]

0 голосов
/ 27 февраля 2020

Вы не можете напрямую «украсть» память у std::vector, но, возможно, вам не нужно красть ее на 1-м месте.

Я не знаком с pybind11::array, но так как вы хотите указатель данных от std::vector, я предполагаю, что вы можете построить его из данных, которые были размещены где-то еще.

Может быть, все, что вам нужно, это класс-оболочка, который будет хранить ваши данные внутри std::vector, обеспечивая при этом просмотр через pybind11::array.

class Wrapper {
public:
  Wrapper(std::vector<char>);
  pybind11::array asArray();

private:
  std::vector<char> m_data
}

Затем вы можете использовать std::move для эффективной передачи данных между std::vector с, без их копирования.

0 голосов
/ 27 февраля 2020

Std :: vector не позволяет отсоединять базовый буфер. Вы также можете взглянуть на захват памяти из std :: vector для аналогичного вопроса.

0 голосов
/ 27 февраля 2020

Конечно, вы можете, потому что это то, что класс std::vector делает для операции перемещения. Но вы не можете портативным способом (*). Во внутреннем классе std::vector вашей реализации вы должны найти способ хранения буфера (какой атрибут используется). В идеале вы должны искать, что делает конструктор перемещения с исходным вектором, и делать то же самое. Скорее всего, он просто установит для внутреннего указателя значение NULL, но вы должны это контролировать.

Просто , как если бы вы использовали неопределенные внутренние компоненты , гарантированно будет работать только эта версия этот компилятор.


С философской точки зрения мы, как программисты, должны использовать классы стандартной библиотеки в том виде, как они . Существует несколько точек расширения и несколько классов, которые можно получить. Это полная противоположность Java, которая предоставляет абстрактные классы, которые помогают программисту создавать свои собственные пользовательские классы.

0 голосов
/ 27 февраля 2020

std::vector не обеспечивает способ передачи своего буфера.

Вы должны сделать некоторую копию (или не использовать std::vector для исходного буфера).

...