簡體   English   中英

在編譯時計算表達式

[英]evaluate expression at compile time

我知道這已經被問了很多,但僅限於 C/C++ 和 Java。 問題與使用常量表達式的性能優勢有關:

當我調用一個只有常量作為參數的靜態函數時,有沒有辦法告訴編譯器它應該在編譯時評估調用並用結果替換調用?

例子:

const double pi = Math.PI; //works as Math.PI is a constant  
const double spi = Math.Sin(Math.PI); //compiler error, because expression must be constant  

是否沒有指令(更好:屬性)明確地告訴編譯器像 Math.Sin() 這樣的靜態方法不會在內部修改或讀取任何數據,以便在技術上可以在編譯時評估調用?

哦,請不要回答像“just do const double spi = 0 ”:),因為我的示例只是我遇到的問題的簡化版本:在保持最大性能的同時提高代碼可維護性。

感謝您的幫助 - 非常感謝!

對於數值常數,我看到兩個選項:

選項一:使用靜態只讀(啟動時計算一次):

class MyCalc
{
    private static readonly double spi = Math.Sin(Math.PI);
    private static readonly double pi = Math.PI;

    public void Execute()
    {
        // .. whatever
    }
}

選項二:使用您的袖珍計算器進行計算並對這些常量進行硬編碼:

class MyCalc
{
    // Math.Sin(Math.Pi)
    private const double spi = 0;
    // Math.Pi
    private const double pi = 3.141592653589793;

    public void Execute()
    {
        // .. whatever
    }
}

我不確定編譯器是否可以在計算中完全優化掉選項一,但它應該是最具可讀性和可維護性的方式。

如果您正在尋找盡可能多的在編譯時做的事情,事情會變得更難。 在 C++ 下,您有模板。 我發現它們寫起來很麻煩,但人們用它完成了驚人的事情 使用 編譯時函數似乎更容易,但我還沒有嘗試過。 D 有CTFE這真的很強大。 但是 D 是一個利基,我會避免在其中編寫任何嚴肅的代碼。 我不知道其他語言有相當明確的預編譯評估,但我確定有一些。

如今,編譯器非常聰明。 編譯器可能會看到有機會在沒有提示的情況下優化函數調用。 在 DotNet 4.5 中,我們獲得了AggressiveInlining屬性,因此我們可以強制編譯器朝着正確的方向發展。 C/C++ 有類似的東西,並且出現了問題 我這邊的一般建議是避免inline直到您完全知道自己在做什么。

如果你真的不想從 C# 走這條路,我認為最好的選擇是使用提到的功能在 C++ 中編寫你的功能,編寫一個易於使用的 C 接口並通過PInvoke調用它。 但是,如果真的值得,請先幫自己一個忙並衡量一下。 永遠不要忘記優化的兩條規則:

  1. 還沒有(僅限專家)

沒有副作用的方法有[Pure]屬性。 但是,這僅用於代碼分析,而不用於編譯器(目前)。 然而,這在未來可能會改變。

JetBrains ReSharper 為相同的目的(代碼分析)提供了類似的[Pure]屬性。

因此,就目前而言,您需要一種解決方法,例如您預先計算的值,最好附上評論,讓其他人知道該值的來源:

const double spi = 0.0; // Math.Sin(Math.PI)

或者

static readonly double spi = Math.Sin(Math.PI);

這當然會計算運行時的值,這是您不想要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM