【问题标题】:Copy the contents of std::vector<char> into a char* buffer?将 std::vector<char> 的内容复制到 char* 缓冲区中?
【发布时间】:2011-12-24 06:34:23
【问题描述】:

我有一个 std::vector。我想将向量的内容复制到一定大小的 char* 缓冲区中。

有安全的方法吗?

我可以这样做吗?

memcpy(buffer, _v.begin(), buffer_size);

还是这个?

std::copy(_v.begin(), _v.end(), buffer); // throws a warning (unsafe)

还是这个?

for (int i = 0; i < _v.size(); i++)
{
  *buffer = _v[i];
  buffer++;
}

谢谢..

【问题讨论】:

  • 我的 C++-fu 有点生疏了,但 char* str = &amp;_v[0]; 不会做这项工作吗?
  • @Polynomial 可能,至少一开始是这样。如果向量曾经重新分配其缓冲区,则位置可能会更改,并且如果向量被破坏,则指针无效。它的风险足够大,可能不是一个的主意。
  • @Polynomial:这不会将向量复制到不同的缓冲区,它只会获取向量中内部缓冲区的地址。
  • @Polynomial:目前这会很好地工作,甚至更快,但是,当您向向量添加一些数据并超出其容量时,它会中断。到时候,它会分配一个新的块并释放你指向的那个。
  • 真正的问题是:为什么要使用char* 缓冲区? std::vector 在(几乎)各方面都好得多。

标签: c++ stl stdvector


【解决方案1】:
std::copy(_v.begin(), _v.end(), buffer);

这是在 C++ 中执行此操作的首选方式。如果buffer 足够大,这种方式复制是安全的。

【讨论】:

  • 这还不够:您应该在末尾添加一个 \0 字符。
  • @AdamZalcman:这不合理。如果向量内容很多\0怎么办?
  • @AdamZalcman:另外,如果这是合理的,那么最初选择std::vector&lt;char&gt; 是错误的,因为std::string 将是一个更好的选择以防万一if char* 需要用 c-string 处理。
  • @AdamZalcman:不。我不认为这是草率的回答。当我看到 std::vector&lt;char&gt; 而不是 std::string 时,我认为 vector 的内容不能保证是 c-string。
  • @krebstar:是的。 vector&lt;char&gt; 保证是一个连续的内存块?。
【解决方案2】:

如果你只需要char*,那么你可以这样做:

char *buffer=&v[0];//v is guaranteed to be a contiguous block of memory.
//use buffer

注意更改buffer 指向的数据也会更改向量的内容!

或者如果你需要一个拷贝,那么分配一个大小等于v.size()字节的内存,并使用std::copy

 char *buffer = new char[v.size()];
 std::copy(v.begin(), v.end(), buffer);

完成后不要忘记delete []buffer;,否则会泄漏内存。

但是那你为什么会提出这样一个需要你自己管理内存的问题..尤其是当你可以做得更好的时候,例如:

auto copy = v; // that's simpler way to make copies!!
// and then use copy as new buffer.
// no need to manually delete anything. :-)

希望对您有所帮助。

【讨论】:

    【解决方案3】:

    vector&lt;char&gt; 复制到char * 缓冲区的最安全方法是将其复制到另一个向量,然后使用该向量的内部缓冲区:

    std::vector<char> copy = _v;
    char * buffer = &copy[0];
    

    当然,如果您实际上不需要复制数据,也可以访问_vs 缓冲区。另外,请注意,如果调整矢量大小,指针将失效。

    如果您需要将其复制到特定的缓冲区中,那么您需要在复制之前知道缓冲区足够大;数组没有边界检查。一旦你检查了尺寸,你的第二种方法是最好的。 (第一个仅在 vector::iterator 是指针时有效,但不能保证;尽管您可以将第二个参数更改为 &amp;_v[0] 以使其工作。第三个做同样的事情,但更复杂,可能应该已修复,因此它不会修改 buffer)。

    【讨论】:

    • 这是几乎最好的。我不这么认为。 +1。
    • 简而言之:提防这种情况:char * buffer;{std::vector&lt;char&gt; copy = _v;buffer = &amp;copy[0];} cout&lt;&lt;buffer;
    【解决方案4】:

    好吧,您想为案例 3 分配给 *buffer,但这应该可以。第一个几乎肯定行不通。

    编辑:我对 #2 的看法得到纠正。

    【讨论】:

    • 无论如何,有没有更快的方法来做到这一点?做一个 for/while 循环似乎很奇怪.. =/
    【解决方案5】:
    static std::vector<unsigned char> read_binary_file (const std::string filename)
    {
        // binary mode is only for switching off newline translation
        std::ifstream file(filename, std::ios::binary);
        file.unsetf(std::ios::skipws);
    
        std::streampos file_size;
        file.seekg(0, std::ios::end);
        file_size = file.tellg();
        file.seekg(0, std::ios::beg);
    
        std::vector<unsigned char> vec(file_size);
        vec.insert(vec.begin(),
                   std::istream_iterator<unsigned char>(file),
                   std::istream_iterator<unsigned char>());
        return (vec);
    }
    

    然后:

    auto vec = read_binary_file(filename);
    auto src = (char*) new char[vec.size()];
    std::copy(vec.begin(), vec.end(), src);
    

    但记得稍后删除[]src

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      相关资源
      最近更新 更多