在C++中什么时候应该使用字符数组而不是字符串?

9

如何区分C++中的char数组和字符串? char数组在哪些方面更胜于std::string?


1
@starboy_jb 标准算法同样适用于字符数组。 - HolyBlackCat
5
来吧,这个问题不必基于个人观点。例如,在 C++20 之前,无法在 constexpr 上下文中使用 std::string,因此我仍然更喜欢将全局常量声明为 const char[],除非我需要对它们进行一些字符串操作。 - Quimby
5
典型的使用情况是当您想要重复使用几十年前编写的旧代码/库时,而不想重新编写! - Damien
6
@Quimby "constexpr"的"string_view"也应该可行。投票重新打开。 - HolyBlackCat
2
@Quimby 你应该把它写成一个答案。 - klutt
显示剩余2条评论
2个回答

4

使用字符数组的一个原因(我个人认为不是非常好的原因)是当你想要让你的代码能够在C编译器和C++编译器中都能够编译时。


1
@bruno 我曾经在自己内心中对此进行了辩论,但我认为这是一个有效的答案。无论这种用例有多么罕见和被误用,它都是一种用例。而且这正是 OP 所要求的 char 数组可以做到而 std::string 不能做到的事情。 - klutt
如果目标也是在C中编译,那么就没有选择,所以也没有问题。;-) - bruno

4
在C++中,我们无需区分 char 数组和字符串。字符串字面量本质上是以null结尾的char数组。由于数组在第一次机会时就会衰减为指针,因此 const char* 通常仍然是 string 的同义词。
如果你想了解何时应该编写 new char[n],答案是从不。如果需要缓冲区,请使用 std::vector 或 std::array ,并且除非编写自己的 std::string 版本,否则请使用标准库中的 std::string。
const char[] 常量相对于 const std::string 有一些优势,但这些优势正在被新的 C++ 标准 "解决":
  1. Before C++20, std::string could not be used in constexpr context. So, I still prefer declaring global string constants with constexpr const char[] if all I do is just passing them to some function. As @HolyBlackCat mentioned in the comments, C++17 std::string_view makes this use-case obsolote too, especially with the new sv literal:

    #include <string_view>
    using namespace std::literals;
    //Compile-time string_view
    constexpr auto str = "hello"sv;
    
  2. const char* is somewhat more universal. You can pass it to a function accepting const char*, std::string, or std::string_view. The reverse requires std::string::c_str() and it is not possible to so without copying the std::string_view.

  3. There is no dynamic allocation involved. Although std::string might employ SSO, it is not guaranteed. This might be relevant for very small systems where the heap is precious and the program flash memory is more accomodating and contains the literal anyway.

  4. Interacting with old libraries. But even then, std::string is null-terminated too.

总的来说,我建议尽可能使用std::string_view——对于任何非拥有字符串,包括持有字符串字面量。最重要的是,它应该替换const char*const std::string&函数参数。如果你想拥有一个字符串,请使用std::string


2
这种建议使用 string_view 的方法存在一个问题:如果您需要调用一个期望只读空终止字符串(例如第三方库)的函数,则必须复制整个查看的字符串以添加终止符,即使字符串视图的源已经有了它。这是一种浪费时间和资源的做法。 - M.M
@M.M 是的,没错,我的建议是针对没有旧依赖的新代码的。这是一种权衡,std::string_view 可以做非后缀基础的子字符串而不需要拷贝,而普通的只读空终止字符串则做不到。 - Quimby

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