什么时候应该使用std::string
,什么时候应该使用C ++char*
管理char
s的数组?
似乎您应该使用char*
性能(速度)是否至关重要,并且由于内存管理,您愿意接受一些冒险的业务。
还有其他情况要考虑吗?
Answers:
您可以通过引用传递std :: strings(如果它们很大以避免复制)或指向该实例的指针,因此我看不到使用char指针有什么真正的好处。
我将std :: string / wstring用于或多或少是实际文本的所有内容。char *
但是对于其他类型的数据很有用,并且您可以确保将其按应有的方式释放。否则,std :: vector是要走的路。
所有这些可能都有例外。
char *
几乎没有开销。std::string
我不知道确切的开销,这可能取决于实现。我几乎不希望开销比裸char指针大得多。由于我没有该标准的副本,因此我无法详细说明该标准所作的任何保证。任何性能差异都可能取决于要执行的操作。std::string::size
可以将大小存储在字符数据旁边,因此比strlen
。
append(const string&)
和append(const char*, size_t)
替代的operator+=()
。
是的,有时候您确实可以做到这一点。当使用const char *,在堆栈上分配的char数组和字符串文字时,您可以用完全没有内存分配的方式来实现。
编写这样的代码通常比使用字符串或向量需要更多的思考和关怀,但是使用适当的技术就可以做到。使用适当的技术,代码可以很安全,但是在复制到char []时,您始终需要确保对复制的字符串的长度有一定的保证,或者可以优雅地检查和处理超大的字符串。不这样做就是给strcpy功能系列以不安全的声誉。
至于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;
}
char*
字符串并不总是在堆栈上。char *str = (char*)malloc(1024); str[1024] = 0;
您必须使用char*
而不std::string
应该使用的一种情况是需要静态字符串常量。这样做的原因是,您无法对订单模块初始化其静态变量进行任何控制,并且来自其他模块的另一个全局对象可能在初始化之前引用了您的字符串。http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std::string
优点:
std::string
缺点:-两个不同的STL字符串实例不能共享相同的基础缓冲区。因此,如果您按值传递,则始终会得到一个新副本。-有一些性能损失,但是我要说,除非您的要求特殊,否则可以忽略不计。
如果要编写库,请使用(const)char *作为参数。不同编译器之间的std :: string实现不同。
您可以期望对std :: string的大多数操作(例如find
)应尽可能优化,因此它们的性能至少可能与纯C语言相当。
还值得注意的是,std :: string迭代器经常映射到指向底层char数组的指针。因此,就性能而言,您在迭代器之上设计的任何算法本质上都与char *之上的相同算法相同。
需要注意的事情是operator[]
-例如,大多数STL实现不执行边界检查,而应将其转换为对基础字符数组的相同操作。AFAIK STLPort可以选择执行边界检查,这时该运算符会慢一些。
那么使用std :: string有什么好处呢?它使您免于手动内存管理;调整数组大小变得更加容易,并且通常不必考虑释放内存。
如果您担心调整字符串大小时的性能,可以使用一个reserve
有用的函数。
即使性能至关重要,您vector<char>
也可以更好地使用它-它可以提前分配内存(reserve()方法),并有助于避免内存泄漏。使用vector :: operator []会导致开销,但是您始终可以提取缓冲区的地址并对其进行完全索引,就像它是char *一样。