如何在没有复制的情况下将`std :: string`强制转换为`std :: vector <unsigned char =“”>`?</unsigned>

时间:2013-05-16 19:21:09

标签: c++ casting stdvector stdstring

我想调用一个库函数,其签名是:

bool WriteBinary(const std::vector<uint8_t> & DataToWrite);

我有一个std::string变量,我想将此函数作为参数发送。

void WriteString(const std::string & TextData)
{
    // ...
    WriteBinary(TextData);  // <-- How to make this line work?
    // ...
}

有没有办法直接发送std::string变量而不复制它?

4 个答案:

答案 0 :(得分:11)

没有办法做到这一点,因为这两种类型的布局不能保证在任何方面都相似。

最好的方法是修复WriteBinary而不是使用“迭代器”:

bool WriteBinary(const unsigned char* first, const unsigned char* last);

或模板化:

template <typename Iter>
bool WriteBinary(Iter first, Iter last);

然后你可以将它用于字符串,向量或任何其他你喜欢的容器!

否则,您可以使用迭代器构造函数尽可能高效地执行复制:

WriteBinary(std::vector<uint8_t>(TextData.begin(), TextData.end()));

答案 1 :(得分:5)

我担心这是不可能的。 stringvector都没有构造函数可以“采用”预先存在的缓冲区。并且stringvector的内存布局很可能不同,因此无法进行转换。

答案 2 :(得分:2)

  

有没有办法可以直接发送std :: string变量而不用   制作它的副本?

不,当然不安全。

如果您可以控制库,我建议稍微重构一下。

添加:

template<typename CharT>
void WriteBinary(CharT const* buffer, size_t count);

或者:

template<typename FwdIter>
void WriteBinary(FwdIter begin, FwdIter end);

然后让现有的WriteBinaryWriteString调用它:

void WriteBinary(std::vector<uint8_t> const& vec)
{ WriteBinary(&*vec.begin(), vec.size()); }

void WriteString(std::string const& s)
{ WriteBinary(&*s.begin(), s.size()); }

或者:

void WriteBinary(std::vector<uint8_t> const& vec)
{ WriteBinary(vec.begin(), vec.end()); }

void WriteString(std::string const& s)
{ WriteBinary(s.begin(), s.end()); }

就个人而言,我更喜欢基于迭代器的方法。感觉“更干净”。

(注意:对于指针/大小方法,您可能希望检查是否为空。如果您在空向量/字符串上推导begin()的结果,某些实现可能会断言。)

答案 3 :(得分:1)

你当然可以自由地通过自己来获得所需的结果。 但是您应该为同事或想要使用/维护/修改或移植代码的人准备摘要执行...

......不要这样做!...

int main (void)
{
  std::string teststring("HERE IS A TEST");
  char * p = (char*)malloc(3*sizeof(char*) + sizeof(std::allocator<char>));
  std::allocator< std::allocator<char> > alloc_alloc;
  char * pa = p + 3*sizeof(char*);
  alloc_alloc.construct((std::allocator<char>*)pa);

  char const * cp = teststring.data();
  char const * * vec_it = (char const**)p;

  vec_it[0] = cp;
  vec_it[1] = cp + teststring.length();
  vec_it[2] = vec_it[1];

  std::vector<char> &a_vector = *((std::vector<char, std::allocator<char>>*)p);

  cout << a_vector.size() << " elements in vector!" << endl;

  for (std::vector<char>::iterator i=a_vector.begin(); i!=a_vector.end(); ++i) 
  {
    cout << *i;
  }
  cout << endl;
  // set char 8 to 66 = B
  a_vector[8] = 66;

  cout << teststring << endl;

}

打印

14 elements in vector!
HERE IS A TEST
HERE IS B TEST

注意:

正如评论中正确提到的,此解决方案依赖于向量具有以下数据布局,并且需要字符串连续存储它的数据(不管这是否由标准预先确定)。

template <typename T>
class vector
{
  T* _first, _last, _end;
  std::allocator<T> _alloc;
};