我应该何时使用std::string
,何时应该使用char*
来管理C ++中char
的数组?
如果性能(速度)至关重要,并且由于内存管理而您愿意接受一些有风险的业务,那么您似乎应该使用char*
。
是否还有其他需要考虑的方案?
答案 0 :(得分:54)
你可以通过引用传递std :: strings如果它们很大以避免复制,或者是指向实例的指针,那么使用char指针我看不到任何真正的优势。
我使用std :: string / wstring来获取或多或少的实际文本。 char *
对其他类型的数据很有用,你可以确定它会像它应该的那样被释放。否则std :: vector就是你的选择。
所有这些都可能有例外。
答案 1 :(得分:54)
我的观点是:
答案 2 :(得分:13)
是的,有时你真的可以做到这一点。当使用const char *,在堆栈上分配的char数组和字符串文字时,你可以这样做,根本没有内存分配。
编写此类代码通常需要比使用字符串或向量更多的思考和关注,但使用适当的技术可以完成。使用适当的技术,代码可以是安全的,但是您总是需要确保在复制到char []时,您要么对要复制的字符串的长度有一些保证,要么优雅地检查和处理超大字符串。不这样做是为了使这些强大的功能系列成为不安全的声誉。
至于char []缓冲安全性,模板可以提供帮助,因为它们可以创建一个封装来为您处理缓冲区大小。像这样的模板被实现,例如由Microsoft提供strcpy的安全替代品。这里的例子是从我自己的代码中提取的,真正的代码有很多方法,但这应该足以传达基本的想法:
template <int Size>
class BString
{
char _data[Size];
public:
BString()
{
_data[0]=0;
// note: last character will always stay zero
// if not, overflow occurred
// all constructors should contain last element initialization
// so that it can be verified during destruction
_data[Size-1]=0;
}
const BString &operator = (const char *src)
{
strncpy(_data,src,Size-1);
return *this;
}
operator const char *() const {return _data;}
};
//! overloads that make conversion of C code easier
template <int Size>
inline const BString<Size> & strcpy(BString<Size> &dst, const char *src)
{
return dst = src;
}
答案 3 :(得分:9)
您需要使用char*
而不是std::string
的一种情况是需要静态字符串常量。原因是您对订单模块没有任何控制来初始化它们的静态变量,而另一个模块中的另一个全局对象可能在它初始化之前引用您的字符串。 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std::string
专业人士:
std::string
缺点:
- 两个不同的STL字符串实例不能共享相同的底层缓冲区。因此,如果您通过值传递,您将始终获得一个新副本。
- 有一些性能损失,但我会说,除非你的要求是特殊的,否则它可以忽略不计。
答案 4 :(得分:8)
在以下情况下,您应该考虑使用char*
:
实际上,在C ++中,char*
通常用于固定的小字,如选项,文件名等......
答案 5 :(得分:5)
何时使用c ++ std :: string:
何时使用char *
答案 6 :(得分:3)
如果要编写库,请使用(const)char *作为参数。 std :: string实现在不同的编译器之间有所不同。
答案 7 :(得分:2)
如果你想使用C库,你将不得不处理C字符串。如果您想将API公开给C,则同样适用。
答案 8 :(得分:2)
您可以期望std :: string(例如find
)上的大多数操作尽可能优化,因此它们可能至少与纯C对应项一样好。
值得注意的是,std :: string迭代器经常映射到指向底层char数组的指针。因此,您在迭代器之上设计的任何算法在性能方面基本上与char *之上的相同算法相同。
需要注意的事项包括: operator[]
- 大多数STL实现不执行边界检查,并且应该将其转换为基础字符数组上的相同操作。 AFAIK STLPort可以选择执行边界检查,此时此运算符会稍微慢一些。
那么使用std :: string可以获得什么?它免除了手动内存管理;调整数组的大小变得更容易,通常你不必考虑释放内存。
如果您在调整字符串大小时担心性能,可能会发现reserve
函数有用。
答案 9 :(得分:1)
如果您在类似文本等中使用字符数组,请使用std :: string更灵活,更易于使用。如果你将它用于其他数据存储?使用数组(首选矢量)
答案 10 :(得分:1)
即使性能至关重要,最好使用vector<char>
- 它允许事先分配内存(reserve()方法)并帮助您避免内存泄漏。使用vector :: operator []会导致开销,但是你总是可以提取缓冲区的地址并将其编入索引,就好像它是一个char *。
答案 11 :(得分:-1)
AFAIK内部大多数std :: string实现copy on write,引用计数语义以避免开销,即使字符串未通过引用传递。