std :: string或std :: vector <char>来保存原始数据</char>

时间:2012-03-08 23:52:45

标签: c++ string

我希望这个问题适合stackoverflow ...在std::string中存储原始数据字节(8位)而不是将它们存储在std::vector<char>之间有什么区别。我正在从文件中读取二进制数据并将这些原始字节存储在std::string中。这很有效,这样做没有任何问题或问题。我的程序按预期工作。但是,其他程序员更喜欢std::vector<char>方法并建议我停止使用std::string,因为它对原始字节不安全。所以我想知道为什么使用std::string来保存原始数据字节会不安全?我知道std::string最常用于存储ASCII文本,但是一个字节是一个字节,所以我不理解std::vector<char>的偏好。

感谢您的任何建议!

3 个答案:

答案 0 :(得分:13)

问题不在于它是否有效或不成功。问题是,对于下一个阅读代码的人来说,这完全令人困惑。 std::string用于显示文字。任何人都在阅读你的代码。您可以使用std::vector<char>更好地声明 intent

它会增加您在代码审核中的WTF/min

答案 1 :(得分:5)

在C ++ 03中,使用std::string来存储字节数据数组并不是一个好主意。根据标准,std::string没有 连续存储数据。 C ++ 11修复了它,因此它的数据必须是连续的。

所以在C ++ 03中这样做是行不通的。除非您亲自审查std::string的C ++标准库实现,以确保它是连续的。

不管怎样,我建议vector<char>。通常,当您看到string时,您希望它是一个...字符串。你知道,某种形式的编码中的一系列字符。 vector<char>显然它不是一个字符串,而是一个字节数组。

答案 2 :(得分:3)

除了连续的存储和代码清晰度问题之外,我还遇到了一些相当隐蔽的错误,试图使用std::string来保存原始字节。

它们中的大多数都集中在与C库接口时尝试将char字节数组转换为std::string。例如:

std::string password = "pass\0word";
std::cout << password.length() << std::endl; // prints 4, not 9

也许你可以通过指定长度来解决这个问题:

std::string password("pass\0word", 0, 9);
std::cout << password.length() << std::endl; // nope! still 4!

这可能是因为构造函数希望接收C字符串,而不是字节数组。可能有更好的方法,但我最终得到了这个:

std::string password("pass0word", 0, 9);
password[4] = '\0';
std::cout << password.length() << std::endl; // hurray! 9!

有点笨重。值得庆幸的是,我在单元测试中发现了这一点,但如果我的测试向量没有空字节,我会错过它。这个阴险的原因是上面的第二种方法可以正常工作直到数组包含一个空字节。

到目前为止std::vector<uint8_t>看起来是一个不错的选择(感谢J.N.和Hurkyl):

char p[] = "pass\0word";
std::vector<uint8_t> password(p, p, p+9); // :)

注意:我没有尝试使用std::string的迭代器构造函数,但是这个错误很容易使得它甚至可能值得避免。

经验教训:

  • 测试包含空字节的测试向量的字节处理方法。
  • 使用std::string保存原始字节时要小心(我会说避免)。