c++ 中的 char* 与 std::string
我什么时候应该使用 std::string
以及什么时候应该使用 char*
来管理 C++ 中的 char
数组?
如果性能(速度)至关重要并且您愿意因内存管理而接受一些有风险的业务,那么您似乎应该使用 char* 。
还有其他场景需要考虑吗?
When should I use std::string
and when should I use char*
to manage arrays of char
s in C++?
It seems you should use char*
if performance(speed) is crucial and you're willing to accept some of a risky business because of the memory management.
Are there other scenarios to consider?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
必须使用
char*
而不是std::string
的一种情况是当您需要静态字符串常量时。 原因是您无法控制模块初始化其静态变量的顺序,并且来自不同模块的另一个全局对象可能在初始化之前引用您的字符串。 http://google-styleguide.googlecode.com/svn/trunk/ cppguide.xml#Static_and_Global_Variablesstd::string
优点:STL 的。
std::string
缺点:- 两个不同的 STL 字符串实例不能共享相同的底层缓冲区。 因此,如果您按值传递,您总是会得到一个新副本。
- 有一些性能损失,但我想说,除非您的要求很特殊,否则它可以忽略不计。
One occasion that you MUST use
char*
and notstd::string
is when you need static string constants. The reason for that is that you don't have any control on the order modules initialize their static variables, and another global object from a different module may refer to your string before it's initialized. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variablesstd::string
pros:of STL.
std::string
cons:- two distinct STL string instances can not share the same underlying buffer. So if you pass by value you always get a new copy.
- there is some performance penalty, but I'd say unless your requirements are special it's negligible.
在以下情况下您应该考虑使用
char*
:实际上,在C++中,
char*
经常用于固定小单词,如选项、文件名等......You should consider to use
char*
in the following cases:Actually, in C++,
char*
are often use for fixed small word, as options, file name, etc...如果您正在编写库,请使用 (const) char* 作为参数。 不同编译器之间的 std::string 实现有所不同。
Use (const) char* as parameters if you are writing a library. std::string implementations differ between different compilers.
何时使用 c++ std::string:
string
比char*
更安全,通常当您使用char*
你必须检查事情以确保事情是正确的,在string
类中,所有这些都为你完成。char*
时,您必须释放分配的内存,而使用string
则不必这样做,因为它在破坏时会释放其内部缓冲区。string
与c++stringstream
配合得很好,格式化IO非常简单。何时使用 char*
char*
可以让您更好地控制幕后发生的事情,这意味着您可以根据需要调整性能。When to use a c++ std::string:
string
s, overall, are more secure thanchar*
, Normally when you are doing things withchar*
you have to check things to make sure things are right, in thestring
class all this is done for you.char*
, you will have to free the memory you allocated, you don't have to do that withstring
since it will free its internal buffer when destructed.string
s work well with c++stringstream
, formatted IO is very easy.When to use char*
char*
gives you more control over what is happening "behind" the scenes, which means you can tune the performance if you need to.如果您想使用 C 库,则必须处理 C 字符串。 如果您想将 API 公开给 C,同样适用。
If you want to use C libraries, you'll have to deal with C-strings. Same applies if you want to expose your API to C.
您可以预期 std::string 上的大多数操作(例如
find
)都会尽可能优化,因此它们的执行效果可能至少与纯 C 对应操作一样好。还值得注意的是,std::string 迭代器经常映射到底层 char 数组的指针。 因此,就性能而言,您在迭代器之上设计的任何算法本质上与在 char * 之上设计的相同算法相同。
需要注意的事情有:
operator[]
- 大多数 STL 实现不执行边界检查,并且应该将其转换为对底层字符数组的相同操作。 AFAIK STLPort 可以选择执行边界检查,此时该运算符会稍微慢一些。那么使用 std::string 会给你带来什么好处呢? 它使您免于手动内存管理; 调整数组大小变得更加容易,并且您通常不必考虑释放内存。
如果您担心调整字符串大小时的性能,您可能会发现
reserve
函数很有用。You can expect most operations on a std::string (such as e.g.
find
) to be as optimized as possible, so they're likely to perform at least as well as a pure C counterpart.It's also worth noting that std::string iterators quite often map to pointers into the underlying char array. So any algorithm you devise on top of iterators is essentially identical to the same algorithm on top of char * in terms of performance.
Things to watch out for are e.g.
operator[]
- most STL implementations do not perform bounds checking, and should translate this to the same operation on the underlying character array. AFAIK STLPort can optionally perform bounds checking, at which point this operator would be a little bit slower.So what does using std::string gain you? It absolves you from manual memory management; resizing the array becomes easier, and you generally have to think less about freeing memory.
If you're worried about performance when resizing a string, there's a
reserve
function that you may find useful.如果您在类似文本等中使用字符数组,请使用 std::string 更灵活且更易于使用。 如果您将其用于其他用途(例如数据存储)? 使用数组(最好是向量)
if you are using the array of chars in like text etc. use std::string more flexible and easier to use. If you use it for something else like data storage? use arrays (prefer vectors)
即使性能至关重要,您也最好使用
vector
- 它允许提前分配内存(reserve() 方法),并帮助您避免内存泄漏。 使用 vector::operator[] 会产生开销,但您始终可以提取缓冲区的地址并对其进行索引,就像它是 char* 一样。Even when performance is crucial you better use
vector<char>
- it allows memory allocation in advance (reserve() method) and will help you avoid memory leaks. Using vector::operator[] leads to an overhead, but you can always extract the address of the buffer and index it exactly like if it was a char*.AFAIK 在内部大多数 std::string 实现了写入时复制、引用计数语义以避免开销,即使字符串不是通过引用传递的。
AFAIK internally most std::string implement copy on write, reference counted semantics to avoid overhead, even if strings are not passed by reference.
您可以通过引用传递 std::string(如果它们很大以避免复制)或指向实例的指针,因此我认为使用 char 没有任何真正的优势指针。
我使用
std::string
/wstring
来处理或多或少的实际文本。 不过,char *
对于其他类型的数据很有用,并且您可以确保它会像应有的那样被释放。 否则std::vector
就是正确的选择。所有这些可能都有例外。
You can pass
std::string
s by reference if they are large to avoid copying, or a pointer to the instance, so I don't see any real advantage usingchar
pointers.I use
std::string
/wstring
for more or less everything that is actual text.char *
is useful for other types of data though and you can be sure it gets deallocated like it should. Otherwisestd::vector<char>
is the way to go.There are probably exceptions to all of this.
我的观点是:
My point of view is:
原始字符串的使用
是的,有时你确实可以做到这一点。 当使用 const char *、在堆栈上分配的 char 数组和字符串文字时,您可以通过根本不分配内存的方式来实现。
编写此类代码通常比使用字符串或向量需要更多的思考和细心,但通过适当的技术是可以完成的。 通过适当的技术,代码可以是安全的,但您始终需要确保在复制到 char [] 时,您要么对被复制的字符串的长度有一些保证,要么优雅地检查和处理过大的字符串。 不这样做就导致了 strcpy 函数家族不安全的名声。
模板如何帮助编写安全的 char 缓冲区
至于 char [] 缓冲区的安全性,模板可以提供帮助,因为它们可以创建一个封装来为您处理缓冲区大小。 像这样的模板是由 Microsoft 实现的,以提供 strcpy 的安全替代品。 这里的例子是从我自己的代码中提取的,真正的代码有很多方法,但这应该足以传达基本思想:
Raw string usage
Yes, sometimes you really can do this. When using const char *, char arrays allocated on the stack and string literals you can do it in such a way there is no memory allocation at all.
Writing such code requires often more thinking and care than using string or vector, but with a proper techniques it can be done. With proper techniques the code can be safe, but you always need to make sure when copying into char [] you either have some guarantees on the lenght of the string being copied, or you check and handle oversized strings gracefully. Not doing so is what gave the strcpy family of functions the reputation of being unsafe.
How templates can help writing safe char buffers
As for char [] buffers safety, templates can help, as they can create an encapsulation for handling the buffer size for you. Templates like this are implemented e.g. by Microsoft to provide safe replacements for strcpy. The example here is extracted from my own code, the real code has a lot more methods, but this should be enough to convey the basic idea: