【发布时间】:2010-10-22 12:29:34
【问题描述】:
什么时候应该使用std::string,什么时候应该使用char* 来管理C++ 中chars 的数组?
如果性能(速度)至关重要并且由于内存管理而愿意接受一些有风险的业务,您似乎应该使用char*。
还有其他需要考虑的情况吗?
【问题讨论】:
什么时候应该使用std::string,什么时候应该使用char* 来管理C++ 中chars 的数组?
如果性能(速度)至关重要并且由于内存管理而愿意接受一些有风险的业务,您似乎应该使用char*。
还有其他需要考虑的情况吗?
【问题讨论】:
我的观点是:
【讨论】:
如果 std::strings 很大以避免复制,或者指向实例的指针,您可以通过引用传递它们,所以我看不出使用 char 指针有什么真正的优势。
我使用std::string/wstring 或多或少地表示所有实际文本。 char * 虽然对其他类型的数据很有用,但您可以确定它会像应有的那样被释放。否则std::vector<char> 是要走的路。
可能所有这些都有例外。
【讨论】:
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 字符串实例不能共享相同的底层缓冲区。因此,如果您按值传递,您总是会得到一个新副本。
- 有一些性能损失,但我会说除非您的要求很特殊,否则可以忽略不计。
【讨论】:
您应该考虑在以下情况下使用char*:
其实在C++中,char*经常用于固定的小字,作为选项、文件名等...
【讨论】:
何时使用 c++ std::string:
strings 比char* 更安全,通常当你使用char* 做事时,你必须检查事情以确保事情是正确的,在string 类中,所有这些都是为你完成的。 char* 时,您必须释放分配的内存,而string 不必这样做,因为它会在销毁时释放其内部缓冲区。strings 与 c++ stringstream 配合得很好,格式化 IO 非常简单。何时使用 char*
char* 可以让您更好地控制“幕后”发生的事情,这意味着您可以根据需要调整性能。【讨论】:
如果您正在编写库,请使用 (const) char* 作为参数。 std::string 实现在不同的编译器之间有所不同。
【讨论】:
如果您想使用 C 库,则必须处理 C 字符串。如果您想将 API 公开给 C,同样适用。
【讨论】:
您可以期望 std::string 上的大多数操作(例如 find)尽可能优化,因此它们的性能可能至少与纯 C 对应物一样好。
还值得注意的是,std::string 迭代器经常映射到指向底层 char 数组的指针。因此,就性能而言,您在迭代器之上设计的任何算法本质上都与基于 char * 的相同算法相同。
需要注意的事情是,例如。 operator[] - 大多数 STL 实现不执行边界检查,应将其转换为对底层字符数组的相同操作。 AFAIK STLPort 可以选择执行边界检查,此时此运算符会慢一些。
那么使用 std::string 有什么好处呢?它使您免于手动内存管理;调整数组大小变得更容易,而且您通常不必考虑释放内存。
如果您在调整字符串大小时担心性能问题,有一个reserve 函数可能对您有用。
【讨论】:
如果您在文本等中使用字符数组,则使用 std::string 更灵活且更易于使用。如果您将其用于数据存储等其他用途?使用数组(首选向量)
【讨论】:
即使性能至关重要,您也最好使用vector<char> - 它允许提前分配内存(reserve() 方法)并帮助您避免内存泄漏。使用 vector::operator[] 会导致开销,但您始终可以提取缓冲区的地址并对其进行索引,就像它是 char* 一样。
【讨论】:
AFAIK 在内部大多数 std::string 实现写入时复制,引用计数语义以避免开销,即使字符串不是通过引用传递。
【讨论】: