1

在 matlab 中,每个类方法看起来都像是一个普通方法,其第一个参数是对象本身。

这种范式对于其他 oop 语言(例如 python)是完全可以接受的,因为类是通过引用传递的。另一方面,matlab 默认情况下按值传递对象(句柄类除外)。

从所有这些我推断,即使使用最简单的 setter 函数(或任何其他类方法)也会导致整个对象被复制。

例如,这是 matlab 中某些类方法的签名:

classdef foo
  methods
    function obj = set.myParam(obj,value);
    function myfun(obj, value);
  end
end

在这种情况下,当我调用 fooObj.myfun(5) (或只是 myfun(fooObj,5))时,matlab 会复制整个 fooObj=foo() 吗?

这不是一个非常大的开销吗?在我看来,为每个类方法(和 setter)复制整个对象似乎非常低效。

我错过了什么吗?在仍然使用 oop 技术的同时,有没有办法在 matlab 中避免这种情况?

我是否必须使用句柄类来防止这种性能开销?

4

1 回答 1

3

如果您希望您的类具有引用语义,那么是的,您需要使用句柄类而不是值类。

但请注意,虽然默认情况下 MATLAB 按值传递参数,但它也使用延迟复制写入时复制,因此只有在需要修改输入参数时才会对输入参数进行复制。此外,如果输入参数是结构或对象,则仅对需要修改的部分(字段、属性)进行复制。

此外,MATLAB 还进行了就地优化,如果输出参数与输入参数相同,并且可以就地完成对输入参数的操作,则无需进行复制。

因此,例如,考虑这个函数:

function y = timestwo(x)
y = 2*x;

如果您从a基础工作区中的变量开始(假设它是一个非常大的双精度数组)并调用b = timestwo(a),则不会复制a,因为x在函数期间不会修改。内存使用仅在分配输出参数时增加y

但是考虑这个函数:

function y = timestwoconj(x)
x = x';
y = 2*x;

现在,在函数执行期间内存使用量会增加,因为在修改时会生成副本x。计算时分配相同的空间y,然后在函数退出时x清除临时副本。

这说明了写入时的复制行为。

还要考虑以下函数:

function x = timestwo(x)
x = 2*x;

这里输出参数与输入参数相同,所有操作都可以就地完成。如果您调用a = timestwo(a),则根本不会进行任何复制,并且内存使用量不会增加。这说明了优化的就地行为。

尝试实现一些与上述类似的功能,将它们应用到一个大数组,然后在调试器中逐行逐行执行它们,同时在任务管理器中观察内存使用情况——你会明白的。

在 MATLAB 中实现值类时,您通常会为您的方法使用语法,例如function obj = myfun(obj, value), 而不是function myfun(obj, value). 方法具有与上述相同的工作方式,因此只有在方法期间修改对象时才会复制对象。

当您使用值类时,这就是您想要发生的事情 - 如果您想要引用语义,请使用句柄类。

希望有帮助!

于 2014-01-27T10:30:01.280 回答