char * vs cd中的std :: string

时间:2009-04-29 07:08:54

标签: c++ stl stdstring arrays

我应该何时使用std::string,何时应该使用char*来管理C ++中char的数组?

如果性能(速度)至关重要,并且由于内存管理而您愿意接受一些有风险的业务,那么您似乎应该使用char*

是否还有其他需要考虑的方案?

12 个答案:

答案 0 :(得分:54)

你可以通过引用传递std :: strings如果它们很大以避免复制,或者是指向实例的指针,那么使用char指针我看不到任何真正的优势。

我使用std :: string / wstring来获取或多或少的实际文本。 char *对其他类型的数据很有用,你可以确定它会像它应该的那样被释放。否则std :: vector就是你的选择。

所有这些都可能有例外。

答案 1 :(得分:54)

我的观点是:

  • 如果您不打电话给“C”代码,请不要使用char *。
  • 总是使用std :: string:它更容易,更友好,优化,标准,它可以防止你有错误,它已被检查并证明有效。

答案 2 :(得分:13)

原始字符串用法

是的,有时你真的可以做到这一点。当使用const char *,在堆栈上分配的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专业人士:

  • 为您管理内存(字符串可以增长,实现将为您分配更大的缓冲区)
  • 更高级别的编程界面,与其余界面完美配合 STL。

std::string缺点: - 两个不同的STL字符串实例不能共享相同的底层缓冲区。因此,如果您通过值传递,您将始终获得一个新副本。 - 有一些性能损失,但我会说,除非你的要求是特殊的,否则它可以忽略不计。

答案 4 :(得分:8)

在以下情况下,您应该考虑使用char*

  • 此数组将在参数中传递。
  • 您事先知道阵列的最大尺寸(您知道它还是强加它)。
  • 您不会对此阵列进行任何转换。

实际上,在C ++中,char*通常用于固定的小字,如选项,文件名等......

答案 5 :(得分:5)

何时使用c ++ std :: string:

    总的来说,
  • 字符串比char *更安全。通常当你使用char *做事情时,你必须检查事情以确保事情是正确的,在字符串类中,所有这些都是为你完成的。
  • 通常在使用char *时,你必须释放你分配的内存,你不必使用字符串,因为它会在被破坏时释放它的内部缓冲区。
  • 字符串与c ++ stringstream配合良好,格式化IO很容易。

何时使用char *

  • 使用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,引用计数语义以避免开销,即使字符串未通过引用传递。