C学习,关于字符串removect

北京中科白癜风医院路线 https://baike.baidu.com/item/北京中科白癜风医院/9728824

函数的功能是从一个由ASCII字符组成的字符串中移除控制字符。看起来它似乎很无辜,但是出于多种原因,这种写法的函数确实性能非常糟糕。而代码清单的remove_ctrl()函数的执行时间在程序整体执行时间中所占的比例非常大。

需要优化的remove_ctrl()

std::stringremove_ctrl(std::strings){std::stringresult;for(inti=0;is.length();++i){if(s[i]=0x20)result=result+s[i];}returnresult;}

remove_ctrl()在循环中对通过参数接收到的字符串s的每个字符进行处理。循环中的代码就是导致这个函数成为热点的原因。if条件语句从字符串中得到一个字符,然后与一个字面常量进行比较。

字符串连接运算符的开销是很大的。它会调用内存管理器去构建一个新的临时字符串对象来保存连接后的字符串。如果传递给remove_ctrl()的参数是一个由可打印的字符组成的字符串,那么remove_ctrl()几乎会为s中的每个字符都构建一个临时字符串对象。

对于一个由个字符组成的字符串而言,这会调用次内存管理器来为临时字符串分配内存,调用次内存管理器来释放内存。

除了分配临时字符串来保存连接运算的结果外,将字符串连接表达式赋值给result时可能还会分配额外的字符串。当然,这取决于字符串是如何实现的。

如果字符串是以写时复制惯用法实现的,那么赋值运算符将会执行一次高效的指针复制并增加引用计数。

如果字符串是以非共享缓冲区的方式实现的,那么赋值运算符必须复制临时字符串的内容。如果实现是原生的,或者result的缓冲区没有足够的容量,那么赋值运算符还必须分配一块新的缓冲区用于复制链接结果。这会导致次复制操作和次额外的内存分配。

如果编译器实现了C++11风格的右值引用和移动语义,那么连接表达式的结果是一个右值,这表示编译器可以调用result的移动构造函数,而无需调用复制构造函数。因此,程序将会执行一次高效的指针复制。

因此,每次执行连接运算时还会将之前处理过的所有字符复制到临时字符串中。如果参数字符串有n个字符,那么remove_ctrl()会复制O(n2)个字符。所有这些内存分配和复制都会导致性能变差。看完这篇文章,是不是对remove_ctrl()函数有所了解呢?那么就赶快和身边喜欢编程的朋友一起分享吧。




转载请注明:http://www.aierlanlan.com/rzgz/3102.html