您知道吗?(Tips Everyday)(8月11日)
假设有这样的函数:
输入两个字符串,一个主串,一个模式串;
要求将主串翻转后再进行模式查找,搜索子串,返回第一个子串的位置;
我们可以这样写:
/* 以下代码未经测试,并没有处理任何异常,仅作为示范代码 */
bool StrMyStr( const char *szSrc, const char *szDest )
{
size_t len = strlen( szSrc );
char *szTemp = new char[len + 1];
memcpy( szTemp, szSrc, len + 1 );
return (strstr( _strrev( szTemp ), szDest ) != 0 );
}
但当我们去测试这段代码的性能时却发现,当处理很长的字串时
char *szTemp = new char[len + 1];
这一句是相当费时的。如果这个函数被频繁调用,那么会极大的影响效率。那么有没有更好的解决方案呢?答案是有的,C++为我们提供了定位的new操作符,从语言的角度上直接支持了内存池。
定位的new的语法:
::new (地址) 类型 [长度];
现在我们的程序可以这样写了:
/* 以下代码在VC.net环境中编译、调试通过,并正常运行 */
/* Creamdog保留所有权力 */
#include <windows.h>
#include <iostream>
using namespace std;
char *g_pBuffer;
bool StrMyStr( const char *szSrc, const char *szDest )
{
size_t len = strlen( szSrc );
char *szTemp = new (g_pBuffer) char[len + 1];
memcpy( szTemp, szSrc, len + 1 );
return (strstr( _strrev( szTemp ), szDest ) != 0 );
}
void main()
{
g_pBuffer = new char[10240];
char a[] = "as;dflkjasdf";
cout << StrMyStr( a, "jkl" );
delete []g_pBuffer;
}
经测,字符串越长效率提升越大。
需要注意的几点:
1. 不要对定位new出来的内存进行delete操作,你只需要重新new就可以了。
2. 如果想用定位new出几块不同的内存,你需要在定位上加上上次new的内存长度的偏移,也就是这样:
char *szTemp1 = new (g_pBuffer) char[len];
char *szTemp2 = new (g_pBuffer + len) char[len];
3. 不要忘记给内存池分配内存,更不要忘记在不用时delete[]它!