ホームページ >バックエンド開発 >C++ >C コンパイラは「新しい」演算子呼び出しを最適化して取り除くことができますか?

C コンパイラは「新しい」演算子呼び出しを最適化して取り除くことができますか?

DDD
DDDオリジナル
2024-12-02 08:49:09895ブラウズ

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::nothrow) 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。