char * vs std ::string在c + +
什么时候应该使用std::string
,什么时候应该用char*
来pipe理C ++中的char
数组?
看来你应该使用char*
如果性能(速度)是至关重要的,并且由于内存pipe理你愿意接受一些冒险的业务。
还有其他情况需要考虑吗?
你可以通过引用传递std :: strings,如果它们很大,以避免复制或指向实例的指针,所以我没有看到使用字符指针的真正优势。
我使用std :: string / wstring或多或less都是实际的文本。 char *
对于其他types的数据是有用的,但是你可以肯定它会被释放。 否则,std :: vector是要走的路。
所有这些可能都有例外。
我的观点是:
- 如果不调用“C”代码,千万不要使用char *。
- 总是使用std :: string:它更容易,更友好,优化,标准,它会防止你有错误,它已被检查并certificate工作。
原始string的使用
是的,有时你真的可以做到这一点。 当使用const char *时,在堆栈和string文字上分配的字符数组,你可以这样做,根本没有内存分配。
编写这样的代码通常需要比使用string或向量更多的思考和关注,但是可以使用适当的技术来完成。 使用适当的技术,代码可以是安全的,但是您总是需要确保在复制到char []时,要么保留所复制string的长度,要么检查并处理超大的string。 不这样做是由于不安全的声誉给了这个function强大的家庭。
模板如何帮助编写安全的字符缓冲区
至于char []缓冲区的安全性,模板可以提供帮助,因为它们可以创build一个用于处理缓冲区大小的封装。 这样的模板例如由微软实现,以提供对strcpy的安全replace。 这里的例子是从我自己的代码中提取的,真正的代码有更多的方法,但是这应该足以传达基本的想法:
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; }
在下列情况下你应该考虑使用char*
- 这个数组将被传入参数。
- 你事先知道你的数组的最大大小(你知道它或者你强加它)。
- 你不会对这个数组做任何转换。
实际上,在C ++中, char*
经常用于固定的小字,作为选项,文件名等等。
有一点你必须使用char *而不是std :: string,当你需要静态string常量的时候。 原因是你没有任何控制命令模块初始化它们的静态variables,另一个来自不同模块的全局对象可能会在初始化之前引用你的string。 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std :: string优点:
- 为你pipe理内存(string可以增长,实现将分配一个更大的缓冲区)
- 更高层次的编程接口,与STL的其他部分很好地协同工作。
std :: string缺点:两个不同的STLstring实例不能共享相同的底层缓冲区。 所以,如果你通过价值传递你总是得到一个新的副本。 – 有一些性能损失,但我会说,除非你的要求是特殊的,它是微不足道的。
何时使用c ++ std :: string:
- 总的来说,string比char *更安全,通常当你用char *做事情时,你必须检查事情以确保事情是正确的,在string类中,所有这些都是为你完成的。
- 通常当使用char *的时候,你将不得不释放你分配的内存,你不需要用string来做这件事,因为它会在被破坏的时候释放它的内部缓冲区。
- string与c ++ stringstream很好地工作,格式化IO非常容易。
何时使用char *
- 使用char *可以更好地控制场景后面发生的事情,这意味着如果需要的话可以调整性能。
如果正在编写库,请使用(const)char *作为参数。 不同编译器之间的std :: string实现有所不同。
如果你想使用C库,你将不得不处理Cstring。 如果您想将您的API暴露给C,则同样适用
你可以期望std :: string上的大多数操作(例如find
)尽可能优化,所以它们可能至less和纯C的操作符一样好。
还值得注意的是,std :: string迭代器通常映射到指向底层char数组的指针。 因此,在迭代器之上devise的任何algorithm在性能上与char *之上的algorithm基本相同。
要注意的是例如operator[]
– 大多数STL实现不执行边界检查,并应将其转换为基础字符数组上的相同操作。 AFAIK STLPort可以select执行边界检查,此时这个运算符会慢一点。
那么使用std :: string会得到什么呢? 它免除你手动内存pipe理; 调整数组的大小变得更容易,而且你通常不得不考虑释放内存。
如果在调整string大小时担心性能,可能会有一个reserve
function,您可能会觉得有用。
如果你正在使用像文本等字符数组使用std ::string更灵活,更容易使用。 如果你把它用于其他的数据存储? 使用数组(更喜欢vector)
即使性能至关重要,您最好使用vector<char>
– 它允许提前分配内存(reserve()方法),并且可以帮助您避免内存泄漏。 使用vector :: operator []会导致开销,但是您总是可以提取缓冲区的地址,并将其索引为如果它是char *。
AFAIK内部大多数std :: string实现拷贝写入,引用计数语义以避免开销,即使string没有被引用传递。