CSDN博客

img ilovevc

C++ vs C 风格的字符串

发表于2005/1/3 15:00:00  1888人阅读

在cdsn上看了一个帖子,谈到std::string的效率比不上c风格的char。因为std::string使用堆,而c风格的字符串数组在很多情况下可以直接使用栈上的空间,极大的提升了速度。

在效率上,C++能够和C抗衡的一个有力武器就是模板template。我试着写成下面一个同样建立在栈上的c++风格的字符串类,效率应该也不错。下面是我的帖子:


效率高的地方使用std::string当然不好,这个涉及到从heap中动态分配内存,而且在多线程runtime dll中可能还需要mutex保护。如果大小必须在运行时才能决定,c也得同样使用malloc等。

我估计你的意思是应该使用c风格的在栈中构造的字符数组,例如char buf[222]。但是这样的问题就是这个buf必须分配足够的大小,这也是缓冲区溢出经常出现的原因。我们假设这个字符串长度足够,使用char数组仍然有个问题就是就是每次strcat的时侯要进行两次类似strlen的操作,当然intel cpu有专门的指令,例如scasb。

但是如果使用c++风格,你可以自己搞个char数组风格的string(而不使用std::string)就可以避免在进行strcat调用时多次获取字符串的长度。
举个例子:

inline size_t cpp_strcpy( char * dest, const char * src)
{
   //copy src to dest and return the copied len
   return strlen( strcpy(dest, src));  //垃圾实现,应该使用汇编
}

template<int size>class local_string
{
public:
 local_string() : len(0){ sz[0] = 0; }
 local_string(const char * str)
 {
  len = cpp_strcpy(sz, str);
  return *this;
 }

 local_string& operator +=(const char * str)
 {
  len += cpp_strcpy(sz + len, str);   //起始地址直接sz+len,避免再次调用字符串长度。
  return *this;
 }

 
 local_string& operator=(const char * str)
 {
  len = cpp_strcpy(sz, str) );
  return *this;
 }

 size_t len() const { return len; }
public:            //public算了。
 char sz[size];
 size_t len;
};

这样以后,在同一个起跑线上(都使用栈上的char×),c++风格的local_string至少不会比c风格的strcat效率低。当然现在我们就需要一个cpp_strcpy,而不是strcpy,该函数不返回一个指针,而是返回拷贝了多长,我上面那个是个垃圾实现,要使用汇编写一个cpp_strcpy的函数应该不难,edi - old_edi就可以实现。
然后使用:
 local_string<40> str;
 str = "hello";
 str += ",";
 str += "world";

效率应该比c风格的高,因为它保存了当前字符串的有效长度。特别在需要多次调用+=的场合。

而后我们需要期待C++编译器将local_string的全部的函数内联,甚至无需实例化具体的local_string类,避免代码膨胀。
---------------
汇编不熟悉,cpp_strcpy就懒得写了,反正我现在工程中也用不上。写完以后看汇编应该是c++风格的效率高,毕竟在operator+=的时侯直接使用sz+len就可以马上获得下一个需要拷贝的位置,而且于字符串长度无关,也就无线性关系。测试倒是不好测试,多次循环总感觉不是很专业,好像又涉及到cache命中率的问题。

这个c++风格的有个毛病就是每个local_string的类型都不一致,妨碍了不同长度的local_string实例之间对象的赋值,参数传递等。应该让它们共用一个基类,将len作为第一个成员。

0 0

相关博文

我的热门文章

img
取 消
img