我设置了o2编译器标志。在多个平台/编译器上测试。完全不使用这两个变量。
const char * temp1 = "a";// optimised away
char * temp2 = new char[1];//not optimised.
第一个变量由于多余而被编译器删除。第二个变量反之。 编译器是否无法检测到该内存块在程序中无处使用?
最初的问题来自真正的产品,当我注意到临时的,未使用的std :: string长度超过15个符号并作为函数的参数传递时,并未得到优化。
asm在线查看: https://godbolt.org/g/Shmx92
编辑: 正如Jarod42提到的那样,clang可以优化两个变量。
答案 0 :(得分:0)
char * temp2 = new char[1];
在这种情况下,您将运算符称为new(sizeof(char)* 1) 实际上是new运算符-是函数的声明(vcruntime_new.h库)。编译后,“ new char [1]”语句将在调用时被替换(asm函数地址)。链接器会将此调用与.obj或.dll中运算符新函数的实际地址绑定在一起。 这就是为什么编译器没有机会知道执行运算符新功能和 它不会优化此语句。
void foo()
{
const char* str = "";
}
void buz()
{
char* str = new char[1];
}
反汇编此功能(无优化):
?foo@@abrakadabra (void __cdecl foo(void)): ; foo's signature
mov dword ptr[ebp - 4], offset $... ; insted ... offset link to table of symbols
;...
?buz@@abrakadabra (void __cdecl buz(void)): ; buz's signature
call ??_U@... ; insted ... mnemonic name of operator new function
mov dword ptr [ebp - 4], eax ; this is simplification
在语句“ call ...”中,编译器无法知道此功能的真正作用。这是链接程序的任务。
备注:汇编程序中的某些代码已简化,以更好地理解
答案 1 :(得分:0)
第一个变量
return redirect()->route('toAnotherController',[$var]);
不在堆上,而是指向只读数据部分。创建字符串“ a”没有副作用,编译器可以安全地对其进行优化。
第二个变量
const char * temp1 = "a";// optimised away
另一方面,呼叫char * temp2 = new char[1];//not optimised.
。这可能会超载,或者可能在libc中设置了一些malloc挂钩,从而产生了副作用。优化这一点将改变程序的行为。编译器知道new何时被重载,并且可以假设它知道底层libc的功能(clang似乎)。但是说我确实设置了一个malloc钩子,然后行为突然改变了。我认为clang无法优化调用效果。
其次,由于您泄漏内存,该代码已损坏。至少应使用temp2调用delete。因此,像您这样的情况永远都不会出现在真实代码中。优化器必须同时看到new和delete调用并确定:
我还发现您不太可能分配内存然后不使用它。为什么不简单地将变量初始化为nullptr?
优化通常会覆盖经常使用的明智代码。