关于char *和string的效率比较

zhjhe 2003-02-11 10:40:46
昨天本人发了“我是教条主义者,请大家将标准C++进行到底”的帖子,网友对其中的一个细节---char *和string的效率---提出了不同看法,现回答如下:
Cybergate:您让我看《The c++ programming language题解》,但没有指明是那个地方,我姑且猜测是练习20。1(不知看对了没有)。

//两个string版本的
string dotconnect (string const &a, string const &b)
{
return a + '.' + b;
}


string dotconnect (string const &a, string const &b)
{
string result(a.size() + b.size() + 1, '.');
result.replace(0, a.size(), a);
result.replace(a.size() + 1, b.size(), b);
reutrn result;
}

//C风格版本的
char * dotconnect (char const *a, char const *b)
{
size_t alen = strlen(a), blen = strlen(b);
char *result = (char *) malloc(alen + blen + 2);
memcpy (result, a, alen);
result[alen] = '.';
memcpy (result + alen + 1, b, blen);
result[alen + blen + 2] = '\0';
return result;
}

作者提到,c风格的版本比string的第二个版本快了大约4倍,但是,正如作者所暗示的,这是一个不公平的测试,下面是另外一个更加不公平的测试,来自《C++ Primer》p82练习3。14。

int main ()
{
int errors = 0;
const char *pc = "a very larg literal string";

for (int ix = 0; ix < 1000000; ++ ix)
{
int len = srlen (pc);
char *pc2 = new char[len + 1];
strcpy (pc2, pc);
if (strcmp (pc2, pc))
++ errors;
delete pc2;
}
}


int main ()
{
int errors = 0;
string str("a very larg literal string");
for (int ix = 0; ix < 1000000; ++ ix)
{
int len = str.size();
string str2 = str;
if (str != str2)
++ errors;
}
}
这里的string版本比char *版本的快两倍。
不公平的大约是这两条语句。
int len = strlen(pc);
int len = str.size();
由于string显式存储长度,而strlen通过遍历整个串来确定长度,所以在执行了1000000次之后,两者的快慢显示出来了。
关于效率的问题,《题解》181面有着较为详细的分析,经过一番考虑后,我认为使用string代替char *,不仅能让我们避免很多麻烦,而且也不会丧失效率,甚至能提高我们的程序的效率(当然,如果您能确定不会出错而且效率问题很重要的话,我也不反对您使用char *)。
实际上各个不同的实现也有着不同的效率,原则上string可以有着非常高的效率,所以,不要简单的认为string的效率不如char *.
再次提倡大家使用 string。同是欢迎任何对我的批评。



...全文
1006 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhjhe 2003-02-12
  • 打赏
  • 举报
回复
感谢bergate的指教。
我的目的不是要证明string比char *快,也许是我的表达有问题造成了您那样的看法。我的本意是想说效率问题不应该是我们不使用string的理由。使用string在大多数情况下并不会比我们直接写出的char *慢。
再次感谢您的批评,同时我愿意就这一问题继续同您商榷。
flashsj 2003-02-12
  • 打赏
  • 举报
回复
我觉得这纯粹是习惯问题
两种方法各有个的好
jacky01081218 2003-02-12
  • 打赏
  • 举报
回复
应该是各有千秋吧~!
不过,我觉得还是C更好一点,方便
ShapeRock 2003-02-11
  • 打赏
  • 举报
回复
是不是太过于细了,没必要在这种地方深究吧。
Cybergate 2003-02-11
  • 打赏
  • 举报
回复
还疏忽了一点,我说的算法复杂度O(n*l),单单指求n次字符串长度的复杂度......
winespirit 2003-02-11
  • 打赏
  • 举报
回复
这样测试吧,

分别在函数中的开始和结束加入GetTickCount获取时间,看看到底谁用的时间多。但个人认为,代码量大并不是主要因素,string由字符组成,我们看到的string只不过是一个封装体,所以我认为从效率上说,是char*快的。这就是方便与效率的矛盾。
Cybergate 2003-02-11
  • 打赏
  • 举报
回复
抱歉,请把delete pc2也提出到循环体外面.
Cybergate 2003-02-11
  • 打赏
  • 举报
回复
是的, strlen是要遍历一次字符串, 但是, 这就公平吗? 我甚至可以说, 你的那段代码并不是一段合格的C风格代码, 至少需要改进. 有点实际经验的c语言程序员都会把strlen和new统统写在循环体外面, 这是基本的代码规范.

如果要扣个大帽子的话, 我说造成string比char*快的原因是你的后两个程序采用的算法不一样, 第一个算法的时间复杂度是O(l*n), 第二格算法的时间复杂度是O(n), 整整差了一个多项式级. 如果你要这样比, 我可以推测就算用java编出来的第二段程序都要比第一段c风格的快, 因为算法不一样.

要记住的是string的底层是用c函数实现的,只是作了包装.STL设计的最初原因是要程序员把精力集中在高层次的算法结构上,而不是最基本的东西,由此提高开发效率.但是致命的核心代码绝对是用C,甚至汇编实现的.

Bjarne Stroustrup提倡初学者学习c++用STL, 其原因之一就是用STL写出的劣质代码和优质代码所产生的效率差距不大. 而C直接和底层打交道, 稍稍的结构差异(随之带来算法的变化)可能就使执行效能产生巨大的反差.

ACM的赛手们用来竞赛是很少用STL的,它们知道效率绝对比不上一段优秀的C代码

最后还有一点,对于某些STL实现,如果=两边内容一样, STL将不进行复制.

如果你一定要比较, 第一段代码应该改进成:

int main ()
{
int errors = 0;
const char *pc = "a very larg literal string";
int len = srlen (pc);
char *pc2 = new char[len + 1];
strcpy (pc2, pc);
for (int ix = 0; ix < 1000000; ++ ix)
{
if (strcmp (pc2, pc))
++ errors;
delete pc2;
}
}

你再比比?

就运行速率而言, C绝对比C++快, 但前提是你必须是一个较好的并有一定算法分析基础的C程序员.
xkak2 2003-02-11
  • 打赏
  • 举报
回复
当然是string更方便些,而且不容易出错。
所谓的效率,更多的是程序员自己的问题,要返回一个类的实例,必须调用几次该类的构造和析构函数,这是每个c++程序员都知道的。这种情况最好使用引用参数,这也是每个c++程序员都知道的(除非你对c++实在不了解)。
B.S说过了,最好忘掉C风格的字符串,使用string。难道大家都忘了?
blue_coco 2003-02-11
  • 打赏
  • 举报
回复
各有所好吧,
Goto到现在还在用啊!
hddhddhdd 2003-02-11
  • 打赏
  • 举报
回复
习惯成自然
效率问题,在现在P4+DDR256M横行的时代,已经意义不是很大了
尤其是作为我们这些

我是改了char *用string的,习惯成自然了
earthharp 2003-02-11
  • 打赏
  • 举报
回复
I think it's much likely to get a error if you use the C-style string--- char*. Because you have to take care of the memory management.
I highly recommend you use std::string instead of char*. Use char* only if you have special need or enough reason.
widewave 2003-02-11
  • 打赏
  • 举报
回复
存在即合理
xkak2 2003-02-11
  • 打赏
  • 举报
回复 1
这根本就是c/c++的效率之争!
c的运行效率比c++高,这是事实。
操作系统一般都用c写,而不是c++(尽管他们用的是c++的编译器来编译)。
但是,如果你不是写操作系统这样的软件,在c++的编译器下统统用c的风格写程序,有没有必要,大家自有公论。
所谓效率,并不全指运行效率,开发、维护的效率在软件业上占的比重是不是更大,自有软件工程的专家研究,我不太了解。
string底层用c函数实现,这谁都知道,c函数的底层还用汇编呢,但是如果不是关键部位,谁用汇编写操作系统?
string到第比直接用char*慢多少,各位有测试数据吗?如果真的要慢一些,是不是值得为运行效率而牺牲开发效率,这是一个工程学问题,不是这里的讨论话题了。
linjpxt 2003-02-11
  • 打赏
  • 举报
回复
我觉得一个好的程序不单表现为代码的效率,由于当今计算机硬件及软件规模的发展,易维护,易读性,可扩展性,可移植性将上升为主要的茅盾,所以,一个好的程序应当是易维护的。从这一点说,如果使用string能比char*做得好,当然提倡用string,但如果保留能char*能使代码更易读,我觉得char*还是可以保留的
rivershan 2003-02-11
  • 打赏
  • 举报
回复
存在即合理

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧