33

当我设计类接口时,我坐下来思考我是否应该经常使用const char*或经常使用const std::string&它,当归根结底时,我经常觉得一只手有 6 个,另一只手有 6 个。

取以下两个函数原型:

void foo(const char* str);
void foo(std::string str);

如果该foo函数要存储一个字符串,我会说第二个是更好的选择,因为它能够传递字符串并在可能的情况下利用移动语义。但是,如果foo只需要读取字符串,const char*解决方案会更好吗?

std::string从性能的角度来看,不需要创建临时的。但是,使用已经存在的字符串作为参数调用函数看起来很突兀:foo(mystr.c_str()). 更糟糕的是,如果将来某个时候需要对阵列进行更高级的操作,或者如果应该存储一个副本,则必须更改接口。

所以我的问题是:

是否有明确定义的(无论是个人的还是其他方面的)惯例来规定何时std::stringconst char*是否是更好的选择?此外,在开始一个新项目时,最好是与使用保持一致还是只选择最适合当前代码块的那个?

4

7 回答 7

53

const char*是对 C 的回归。我想说的是,在体面的 C++ 中,它的唯一用途是在extern "C"API 中。

std::string有很多优点:

  1. 它提供了一个恒定时间的size()功能。发现 a 的长度const char*需要线性时间。

  2. 保证有效。必须检查Aconst char*是否为空,并且完全有可能传递不正确的数据 - 数据缺少空终止符。这种情况几乎肯定会导致崩溃或更糟。

  3. 它与标准算法兼容。

如果您担心必须创建 astd::string来调用函数会影响性能,请考虑采用标准库使用的方法 - 将函数更改为采用一对迭代器。然后,您可以提供一个方便的重载,将const std::string&委托给迭代器对。

于 2014-04-30T08:47:31.243 回答
21

只是个人经验的一些笔记。如果您正在开发一个 c++ 项目(根据您添加的标签),请std::string尽可能多地使用提供的内容。不要试图重新发明最基本的结构,万能的弦。我看到了几个项目,他们重新发明了基本弦乐,然后花了几个月的时间对其进行微调。

如果您的 c++ 项目从您引入char*变量的那一刻起就回退到标准 C 函数,例如strlen()strcpy(仅举两个例子......)。从这一点开始,您的项目开始变得一团糟,手动管理内存分配等......

如果您需要与接受作为其参数的第三方库进行交互const char*(并且我想您信任这些库 - 即:您相信他们不会const_cast放弃用您糟糕的字符串做坏事的常量),您可以使用std::string::c_str()它来const char*退出你的字符串。

如果您需要与具有接受方法的库进行交互,char*我强烈建议您获取字符串的副本c_str()并将其用作库的传入参数(当然,不要忘记删除额外的副本)。

除了这些额外的点,我只是订阅了 Angew 回复中的所有三点。

于 2014-04-30T08:57:06.007 回答
6

std::string应该始终是 C++ 中的首选。为避免额外的复制开销,您几乎应该始终将参数作为引用传递,const并尽可能随时随地引用。

在那种情况下,你的函数签名会变成这样

无效 foo(std::string &str);

如果参数是 const 就像这样

void foo(const std::string &str);

您可以在此处查看此 const 关键字的好处

于 2014-04-30T08:45:43.887 回答
4

std::string 比使用 raw char * 更好,您必须管理分配、解除分配和与大小相关的问题,以小心任何溢出、下溢,您没有越过大小边界。而 std::string 这些都是通过抽象处理的

于 2014-04-30T08:45:12.903 回答
4

而不是使用

void foo(std::string str); 

你可以使用

void foo(const std::string& str);

相当于

void foo(const char* str);

在使用方面,因为在传递引用时没有分配内存。但是对于 C++ 中的字符串,我肯定会使用std::string. 对于随机数据或 C 兼容接口,我不会。

于 2014-04-30T08:45:40.140 回答
3

如果您想更好地处理您的数据(在您的情况下它将是字符串),我会说使用 char *。它将让您更好地访问您的字符串和内存利用率。但是,如果您不必担心性能和内存管理问题,那么您可以轻松使用 std::string。

于 2014-04-30T14:31:58.560 回答
1

好吧,我会稍微改一下你的问题。您应该询问何时应使用字符数组而不是std::string.

string这是因为除非您不能使用它,否则您应该始终使用它。因此,您应该使用字符数组而不是string

  1. 使用支持的 API,C因此您无法使用string.
  2. exe在和之间传递数据dll。不建议在和之间交换具有构造函数和/或析构函数的数据exe类型dll

如果您担心性能,在启用所有优化的编译后string变得类似于字符数组,在某些情况下可能会提供更好的性能,例如如果您需要获取它包含的字符数。

另外关于性能,你总是可以通过引用传递,正如其他答案所提到的,如果你必须传递一个指向字符数组的指针,你可以使用c_str()返回const指向第一个字符的指针的方法,如果你必须传递指针(不是const指针)你可以(但实际上不应该)像这样传递它:&str[0].

于 2014-05-06T14:32:54.083 回答