在F#中返回非常大的数据效率如何?

时间:2010-09-10 03:05:15

标签: f# functional-programming stack heap return-value

假设我们在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;
}

现在,观察在F#中,矩阵res分配在堆内存中,与C ++版本相比,它在中分配res堆栈记忆

到目前为止一切顺利。观察当我们想要在两个版本中对sum运算的结果使用“ reference ”时会发生什么:

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 ++中的对应运算符效率更高,因为复制行为浅而深?

3 个答案:

答案 0 :(得分:3)

通常,将数据保存在堆栈上会更快。商业级C ++编译器通常使用"return value optimization"

但是在你开始真正衡量表现之前,你永远不会知道哪个更快。涉及的因素太多了。

答案 1 :(得分:2)

是的,F#(作为C#和VB.NET)通过引用传递对象(类实例)(因此没有创建副本),如果你使用结构(在C#中,不确定你是否可以在F#中创建这样的东西)然后它们按值传递(因此创建了副本)。请注意,在C ++中,您也可以双向完成。但是,是的,你提出你的例子的方式,F#解决方案会更有效率。

唉,有人可能会指出,如果你让Matrix成为一个可变对象,那么你将会更加高效(因为不需要创建新的Matrix对象),但是你失去了所有不变性的优点。 / p>

答案 2 :(得分:2)

.NET具有引用和值类型,并且在堆栈上分配值类型(除非它们是引用类型的一部分,但是不要让它们被带走)。在C#中,您将分别使用classstruct关键字声明它们。

虽然这不是F#类型声明语义的一部分,但您可以通过使用[<Struct>]属性告诉编译器将特定类型创建为值类型。