1

F# に Matrix クラスがあり、(+) 演算子をオーバーロードするとします。次に、次のようになります。

type Matrix(n : int, m : int) = 
    ...
    static member (+) (A : Matrix, B : Matrix) = 
        let res = new Matrix(A.Dim1, A.Dim2) // suppose A and B have the same dimension
        ... // compute here the sum
        res

C/C++ と比較すると、次のようになります。

static const Matrix operator+(const Matrix& A, const Matrix& B)
{
    Matrix res(A.Dim1(), A.Dim2());
    ... // compute here the sum
    return res;
}

ここで、スタック メモリに割り当てられる C++ バージョンとは対照的に、F# では行列resヒープ メモリに割り当てられることに注意してください。res

ここまでは順調ですね。両方のバージョンで合計演算の結果への「参照」が必要な場合に何が起こるかを観察します。

Matrix result = A + B; // deep copy in C++ (because res has to be destroyed after its return)

let result = A + B // shallow copy in F# (res was allocated in the heap memory)

ここで何かが欠けているのでしょうか、それとも F# の (+) 演算子は、浅いコピーと深いコピーの動作のために、C/C++ の対応する演算子よりも効率的になりますか?

4

3 に答える 3

3

通常、スタックにデータを保持する方が高速です。また、商用グレードの C++ コンパイラは、多くの場合、「戻り値の最適化」を使用します。

しかし、実際にパフォーマンスを測定し始めるまで、どちらが速いかはわかりません。あまりにも多くの要因が関係しています。

于 2010-09-10T07:43:24.830 に答える
2

.NETには参照型と値型があり、値型はスタックに割り当てられます(参照型の一部である場合を除きますが、夢中にならないようにします)。classC#では、それぞれとstructキーワードを使用して宣言します。

[<Struct>]これは実際にはF#型宣言セマンティクスの一部ではありませんが、属性を使用して、値型として特定の型を作成するようにコンパイラーに指示できます。

于 2010-09-10T10:45:41.870 に答える
2

Yep, F# (as C# and VB.NET) passes objects (class instances) by reference (so no copies created), if you use structs (in C#, not sure if you can create such a thing in F#) then they are passed by value (thus copies are created). Note that in C++ you can do it both ways too. But, yes, the way you propose your example, the F# solution is going to be more efficient.

Alas, somebody would probably point out that if you make Matrix a mutable object then you'll be even more performant (as no new Matrix objects need to be created), but then you loose all of the goodness of immutability.

于 2010-09-10T04:15:13.227 に答える