当我设计类接口时,我常常坐下来思考是否应该经常使用const char*
或const std::string&
,当它归结为它时,我常常觉得有6个另一方面,另一方面有六打。
采用以下两个函数原型:
void foo(const char* str);
void foo(std::string str);
如果foo
函数存储一个字符串,我会说第二个是更好的选择,因为能够传递字符串并尽可能利用移动语义。但是,如果foo
只需要读取字符串,那么const char*
解决方案会更好吗?
从性能角度来看,不需要创建临时std::string
。但是,使用已存在的字符串作为参数调用该函数看起来很突出:foo(mystr.c_str())
。更糟糕的是,如果需要在未来的某个时刻对阵列进行更高级的操作,或者如果应该存储副本,则接口必须更改。
所以我的问题是:
在std::string
或const char*
是更好的选择时,是否有明确定义的个人或其他约定?此外,在开始一个新项目时,最好是与用法保持一致,还是只选择最适合当前代码块的那个?
答案 0 :(得分:51)
const char*
是C的回归。我会说在体面的C ++中,关于它的唯一用途是extern "C"
API。
std::string
有许多优点:
它提供了一个恒定时间size()
功能。发现const char*
的长度需要线性时间。
保证有效。必须检查const char*
是否为空,并且完全可以传递不正确的数据 - 数据缺少空终止符。这种情况几乎可以保证导致崩溃或更糟。
它与标准算法兼容。
如果您担心必须创建std::string
来调用该函数会对性能产生影响,请考虑采用标准库使用的方法 - 将函数更改为使用一对迭代器。然后,您可以提供一个方便的重载,将const std::string&
委托给迭代器对。
答案 1 :(得分:19)
个人经历中的一些注释。如果您正在处理一个c ++项目(根据您添加的标记),请尽可能多地提供std::string
。不要试图重新发明所有结构中最基本的结构,即全能的字符串。我看到几个项目,他们重新发明了基本的字符串,然后花了几个月微调它。
如果您的c ++项目从您引入char*
变量的那一刻开始,您将回归到标准C函数,例如strlen()
和strcpy
(仅举两个... )。从这一点开始,你的项目开始变得混乱,手动管理内存分配等......
如果您需要与接受const char*
作为参数的第三方库进行交互(我认为您信任这些库 - 即:您相信他们不会const_cast
远离常量做恶你可怜的字符串)你可以使用std::string::c_str()
从字符串中获取const char*
。
如果您需要与接受char*
方法的库进行交互,我强烈建议您复制字符串的c_str()
并将其用作库的输入参数(当然,请执行此操作)不要忘记删除额外的副本。)
除了这些额外的观点之外,我只赞同Angew的回应中的所有三点。
答案 2 :(得分:6)
std::string
应始终是c ++的首选。为避免额外的复制开销,您几乎应该始终将参数作为参考传递,并尽可能地const
引用。
在这种情况下,您的功能签名将变为如此
void foo(std :: string& str);
并且像这样,如果参数是const
void foo(const std :: string& str);
这个const关键词有好处,你可以看here
答案 3 :(得分:4)
std :: string比使用原始字符*更好,你必须管理分配,解除分配和大小相关的问题,要小心任何溢出,下溢,你没有超过大小边界。而std :: string这些都是通过抽象来处理的
答案 4 :(得分:4)
而不是使用
void foo(std::string str);
你可以使用
void foo(const std::string& str);
等同于
void foo(const char* str);
就使用而言,因为在传递引用时没有分配内存。但对于C ++中的字符串,我绝对会使用std::string
。对于随机数据或C兼容接口,我不会。
答案 5 :(得分:3)
如果你想更好地处理你的说法数据(在你的情况下,它将是字符串)我会说与char *一起去。它将使您更好地访问字符串和内存利用率。 但是,如果您不必担心性能和内存管理问题,那么您可以轻松地使用std :: string。
答案 6 :(得分:1)
好吧,我会稍微改一下你的问题。您应该询问何时应使用字符数组而不是std::string
。
这是因为您应该始终使用string
,除非您不能使用它。所以你应该使用characters数组而不是string
的情况:
C
的API,因此您无法使用string
。exe
和dll
之间传递数据。建议不要在exe
和dll
之间交换具有构造函数和/或析构函数的数据类型如果您担心性能,在使用所有已启用的优化进行编译后string
变得类似于字符数组,在某些情况下可能会提供更好的性能,例如,如果您需要获取它包含的字符数。
另外关于性能,你可以随时通过引用传递,如同你提到的其他答案一样,如果你必须将指针传递给字符数组,你可以使用方法c_str()
,它首先返回const
指针如果你必须传递指针(不是const
指针)你可以(但实际上不应该)传递它,如下所示:&str[0]
。