在代码优化中使用new运算符是否值得?

Is it worth to use new operator in code optimization?

本文关键字:运算符 是否 值得 new 代码优化      更新时间:2023-10-16

我有两段代码。第一个代码片段似乎很慢

char*    ptrString = "Some string, maximum 4096 characters...";
size_t   sLen = strlen(ptrString);
WCHAR*   wchrText = new WCHAR[sLen+1];
size_t   i;
for(i=0; i<sLen; i++)
{
    if ( ptrString[i]=='A' ) break;
    wchrText[i] = ptrString[i];
}
//printf(wchrText);

我决定移除strlenif。然后我想到了下面的代码片段

WCHAR*   wchrText = new WCHAR[4096];
size_t   i=0;
while(ptrString[i] != 'A')
{
    wchrText[i] = ptrString[i];
    i++;
}
//printf(wchrText);

这里我必须取wchrText, 4096长。我期待有一个更快的执行,但没有任何明显的改善,或者我无法证明!是第二个代码片段中的new操作符降低了速度吗?有没有更好的解决办法?

代码语法和内存使用不重要

啊,你一开始骗了我,这两个循环应该根据编译器和设置优化为相同的代码,但实际上没有任何区别。

one.c:

char*           ptrString = "Some string, maximum 4096 characters...";
unsigned int    sLen;
char            wchrText[4097];
int             i;
void one ( void )
{
    sLen = 4096;
    for(i=0; i<sLen; i++)
    {
        if ( ptrString[i]=='A' ) break;
        wchrText[i] = ptrString[i];
    }
}

two.c:

char*           ptrString = "Some string, maximum 4096 characters...";
unsigned int    sLen;
char            wchrText[4097];
int             i;
void two ( void )
{
    sLen = 4096;
    i=0;
    while(ptrString[i] != 'A')
    {
        wchrText[i] = ptrString[i];
        i++;
    }
}

但他们没有。一个是更多的代码。然后我意识到你的两个循环是不相等的。第二个循环对I变量没有限制检查,它可以通过ram运行超过字符串的长度,直到遇到不应该碰到的字符或找到该字符。

所以当我让这两个例子相同时:

one.c:

char*           ptrString = "Some string, maximum 4096 characters...";
unsigned int    sLen;
char            wchrText[4097];
int             i;
void one ( void )
{
    sLen = 4096;
    for(i=0; /*i<sLen*/; i++)
    {
        if ( ptrString[i]=='A' ) break;
        wchrText[i] = ptrString[i];
    }
}

我得到了每个解决方案完全相同的代码,正如预期的那样:

00000000 <one>:
   0:   e59f3044    ldr r3, [pc, #68]   ; 4c <one+0x4c>
   4:   e59f2044    ldr r2, [pc, #68]   ; 50 <one+0x50>
   8:   e59f0044    ldr r0, [pc, #68]   ; 54 <one+0x54>
   c:   e5931000    ldr r1, [r3]
  10:   e3a0ca01    mov ip, #4096   ; 0x1000
  14:   e3a03000    mov r3, #0
  18:   e582c000    str ip, [r2]
  1c:   e5803000    str r3, [r0]
  20:   e5d12000    ldrb    r2, [r1]
  24:   e3520041    cmp r2, #65 ; 0x41
  28:   012fff1e    bxeq    lr
  2c:   e59fc024    ldr ip, [pc, #36]   ; 58 <one+0x58>
  30:   e7cc2003    strb    r2, [ip, r3]
  34:   e2833001    add r3, r3, #1
  38:   e5803000    str r3, [r0]
  3c:   e5f12001    ldrb    r2, [r1, #1]!
  40:   e3520041    cmp r2, #65 ; 0x41
  44:   1afffff9    bne 30 <one+0x30>
  48:   e12fff1e    bx  lr

如果我修改第二个函数来匹配第一个而不是第一个函数来匹配第二个

two.c:

char*           ptrString = "Some string, maximum 4096 characters...";
unsigned int    sLen;
char            wchrText[4097];
int             i;
void two ( void )
{
    sLen = 4096;
    i=0;
    while(ptrString[i] != 'A')
    {
        wchrText[i] = ptrString[i];
        i++;
        if(i<sLen) ; break;
    }
}

它没有优化到相同的代码,仍然在挠我的头在那一个

忽略内存分配并简单地比较循环性能,在所有条件相同的情况下,无论整数比较花费多少时间,第二个代码片段都会更快。考虑到不超过4096次迭代,我怀疑它会在现代硬件上产生可测量的差异。

,

如果你不能保证你的源字符串将总是,没有例外,包含一个'A'字符,那么第二个片段是极其不安全的,因为如果源不包含'A',你将超出源和目标数组。更不用说您没有正确地终止目标字符串。

你需要保持长度检查,或者你需要寻找0结束符:

while ( ptrString[i] && ptrString[i] != 'A' )
   ...

不要忽视安全