如何将C ++ std :: vector <char>的所有权转移到char *指针

3
我遇到了这样的情况:我从一个第三方库得到了一个非常长的数据,它是一个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]<<",";处崩溃。


std::vector::data能解决问题吗? - NutCracker
6
std::move(vec); 这行代码实际上什么也没做。 - Fareanor
1
“return p_vec;”会返回一个指向本地数据的指针,一旦函数返回,向量对象(以及它维护的数据)将结束其生命周期,指针将立即变为无效。解决方案很简单:返回向量本身。 - Some programmer dude
@Fareanor,非常感谢您的快速回复。我知道问题出在哪里了,我写测试代码只是为了更清楚地展示我想要实现的内容。我需要按照测试代码中的实现方式来编写代码,并使其正常工作。 - rockofz
1
如果给定标签[tag:pybind11],那么阅读绑定STL容器部分会让我想到bind_vector的目的是什么? - acraig5075
显示剩余7条评论
4个回答

1

0

std::vector 不提供传输其缓冲区的方式。

您必须进行一些复制(或不使用 std::vector 作为原始缓冲区)。


1
这真是太遗憾了。在某些情况下,这可能非常有用。 - Timo

0
当然可以,因为这就是std::vector类在移动操作时所做的。但你不能以可移植的方式实现(*). 你必须查找你所使用的std::vector类的内部实现,了解缓冲区是如何存储的(使用了哪个属性)。理想情况下,你应该查找移动构造函数对源向量所做的操作,并执行相同的操作。很可能只需将内部指针设置为NULL,但你应该控制它。
由于你将使用未指定的内部实现,因此只能保证在该编译器版本上运行。
从哲学的角度来看,我们作为程序员应该使用标准库中的类“原样”。有一些扩展点,但是很少有类允许被派生。这与 Java 正好相反,Java 提供抽象类来帮助程序员构建自己的自定义类。

0

你不能直接从一个std::vector中“窃取”内存,但也许你在第一时间就不需要这么做。

我不熟悉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 之间传输数据。


很遗憾的是,即使pybind11::array可以从数组构造,它仍然需要进行内存分配和memcpy,它无法窃取vector的内存所有权。因为Python对象在C++端之外使用,我们不知道何时会释放它,所以pybind11::array应该拥有内存并稍后自行释放它。这真的让我感到惊讶,因为这超出了我对C++能做什么的期望! - rockofz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接