我可以从它包含的数据中分离std :: vector <char>吗?</char>

时间:2010-09-08 12:12:49

标签: c++ stl vector

我正在使用一个函数,它产生一些数据作为std::vector<char>,另一个函数(想想遗留API)处理数据并采用const char *, size_t len。是否有任何方法可以从向量中分离数据,以便在调用处理函数之前向量可以超出范围而不用复制向量中包含的数据(这就是我用分离)。

一些代码草图来说明场景:

// Generates data
std::vector<char> generateSomeData();

// Legacy API function which consumes data
void processData( const char *buf, size_t len );

void f() {
  char *buf = 0;
  size_t len = 0;
  {
      std::vector<char> data = generateSomeData();
      buf = &data[0];
      len = data.size();
  }

  // How can I ensure that 'buf' points to valid data at this point, so that the following
  // line is okay, without copying the data?
  processData( buf, len );
}

4 个答案:

答案 0 :(得分:15)

void f() { 
  char *buf = 0; 
  size_t len = 0; 
  std::vector<char> mybuffer; // exists if and only if there are buf and len exist
  { 
      std::vector<char> data = generateSomeData(); 
      mybuffer.swap(data);  // swap without copy
      buf = &mybuffer[0]; 
      len = mybuffer.size(); 
  } 

  // How can I ensure that 'buf' points to valid data at this point, so that the following 
  // line is okay, without copying the data? 
  processData( buf, len ); 
} 

答案 1 :(得分:4)

最简单的解决方案尚未公布:

void f() { 
   std::vector<char> data = generateSomeData(); 

  processData( &data[0], data.size() ); 
} 

答案 2 :(得分:1)

我正在回答以下原始问题。但是请记住,在大多数情况下,使用vector::data()并重新组织代码,以使所提到的向量不会超出范围,请使用以vector(std::move(otherVector))初始化的另一个向量,或与另一个向量交换内容({ {1}})是其他答案中指出的更好的选择。

但是,有一种方法可以使用自定义分配器实际分离向量的数据。以下实现了绝对不执行任何操作的分配器vector::swap(otherVector)。它既不分配/构造东西,也不分配/破坏东西。而且它不包含任何非静态或虚拟成员变量。因此,它不应更改Noalloc实例的内容。在vector内部,我们通过重新解释类型将普通向量转换为使用上述分配器类型的向量,并将其内容移至具有相同分配器的新向量。当新向量超出范围时,它将尝试破坏和释放其数组内容。但是,由于我们已经覆盖了自定义分配器中的功能,因此这绝对不会执行任何操作。该函数返回一个指向原始向量新分离的数据的指针(该向量现在将nullptr用作数据和零元素)。 之后不要忘记手动销毁并重新分配数组中的元素!

detachData

答案 3 :(得分:-6)

我不推荐它,但是:

char* ptr = NULL;
int len = -1;
{
    vector<char> vec;
    /* ... fill vec with data ... */
    vec.push_back(NULL); // dont forget to null terminate =)
    ptr = &vec.front();
    len = vec.size();
    // here goes...
    memset((void*)&vec, 0, sizeof(vec));
}
// vec is out of scoop, but you can still access it's old content via ptr.
char firstVal = ptr[0];
char lastVal = ptr[len-1];
delete [] ptr; // don't forget to free

瞧!

这段代码实际上非常安全,因为vec的析构函数将调用delete [] 0;,这是一个安全的操作(除非你得到一些奇怪的stl实现)。