首页 >后端开发 >C++ >C 编译器可以优化掉'新”运算符调用吗?

C 编译器可以优化掉'新”运算符调用吗?

DDD
DDD原创
2024-12-02 08:49:09910浏览

Can a C   Compiler Optimize Away `new` Operator Calls?

编译器可以优化堆内存分配吗?

考虑以下使用 new 运算符分配内存的简单 C 代码:

int main()
{
    int* mem = new int[100];
    return 0;
}

编译器能否优化新的调用,从而避免动态内存分配?

编译器行为

不同的编译器在这种情况下的行为不同。 g 和 Visual Studio 2015 不会优化新调用,而 clang 会优化,正如在启用完全优化的测试中观察到的那样。

编译器优化原理

根据 N3664 :澄清内存分配,后来成为 C 14 的一部分,允许编译器围绕内存分配进行优化。这种优化是基于新调用没有可观察到的副作用的假设。

As-If 规则

但是,草案中的 as-if 规则C 标准第 1.9 节要求一致的实现来模拟抽象机的可观察行为。从 new 中抛出异常会产生明显的副作用,因此可以认为编译器不允许优化 new 调用。

实现细节

On另一方面,可以说何时从 new 中抛出异常的决定是一个实现细节。 Clang 可能会确定分配不会导致异常,因此在不违反 as-if 规则的情况下忽略新调用。

非抛出分配

使用new 的非抛出版本 new (std::nothrot) int[100] 仍然允许 clang 优化分配。这是因为 clang 可能能够证明不存在可能导致可观察行为的全局替换运算符 new。

积极优化

在 clang 的早期版本中,甚至进行了更积极的优化,如以下代码所示:

#include <cstddef>

extern void* operator new(std::size_t n);

template<typename T>
T* create() { return new T(); }

int main() {
    auto result = 0;
    for (auto i = 0; i < 1000000; ++i) {
        result += (create<int>() != nullptr);
    }
    return result;
}

此代码已优化to:

main:                                   # @main
    movl    00000, %eax          # imm = 0xF4240
    ret

实际上,整个循环都被优化掉了。更高版本的 clang 不会执行如此激进的优化。

以上是C 编译器可以优化掉'新”运算符调用吗?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn