简体   繁体   English

MatLab 无法就地修改数据

[英]MatLab can't modify data in place

I have issues with functions that operate in place with MatLab.我对使用 MatLab 就地运行的功能有疑问。 I've also read Loren's blog on in-place operation on MatLab, and the example there is a bit lacking.我还阅读了 Loren 关于 MatLab 就地操作的博客,其中的示例有点欠缺。 First, let me show you a function:首先,让我向您展示一个功能:

    % a method of my_class < handle
    function obj = ip_find(obj, value)
        if value == obj.value
            return
        elseif value < obj.value
            if isa(obj.left, 'Node')
                obj = ip_find(obj.left, value);
            else
                obj = nan;
            end
        else 
            % similar to above
        end
    end

The function ip_find is an in-place operation that works as intended (to specify, ip_find is a method of my_class < handle , and returns a my_class object).函数ip_find是按预期工作的就地操作(指定, ip_findmy_class < handle的方法,并返回my_class对象)。 Here is what I mean: suppose that the I'm looking for data1 using ip_find() , and I set x=ip_find(arg) .这就是我的意思:假设我正在使用ip_find()寻找data1 ,并且我设置x=ip_find(arg) If I then modify x , then data1 is also modified, x is not only a copy of data1 .如果我然后修改x ,那么data1也被修改, x不仅是data1的副本。

Now please take a look at this function below ( priv_delete works as intended, set is a method of matlab.mixin.SetGet ):现在请看下面的这个函数( priv_delete按预期工作, setmatlab.mixin.SetGet的一个方法):

    function delete23(obj, value)
        [left, right] = neighbours(obj, value);
        lvalue=nan;rvalue=nan;

        if isa(left, 'Node_augmented')
            lvalue = left.value;
        end
        if isa(right, 'Node_augmented')
            rvalue = right.value;
        end

        % priv_delete works as intended, the issue is not here
        obj.root = priv_delete(obj.root, value);

        if ~isnan(lvalue)
            lnode = ip_find(obj.root, lvalue);
            if ~isnan(rvalue)
                rnode = ip_find(obj.root, rvalue);
                set(lnode, 'suc', rnode);  % <---- issue
            else  % then right is nan
                set(lnode, 'suc', nan);    % <---- issue
            end
        end
        if ~isnan(rvalue)
            % similar to above
        end
    end

The issue is with the lines where I invoke set .问题在于我调用set的行。 It appears to be that I'm operating on a copy of the data, instead of directly on the data.似乎我正在对数据的副本进行操作,而不是直接对数据进行操作。 Thus my tests fail, as I only modified the copies!因此我的测试失败了,因为我只修改了副本! I'm not sure what is wrong, I can't seem to find the bug.我不确定出了什么问题,我似乎找不到错误。 I have thought of using pointers but MatLab does not even support it.我曾想过使用指针,但 MatLab 甚至不支持它。

I think you confuse the concept of “in place operation” (a function that modifies its input directly, instead of copying it first), and “handle object” (an object that points at data, so that when it's copied, the copy points at the same data).我认为你混淆了“就地操作”(一个直接修改其输入的函数,而不是先复制它)和“处理对象”(一个指向数据的对象,这样当它被复制时,复制点相同的数据)。

Where you do你在哪里

set(lnode, 'suc', rnode);

you modify lnode , which is a local variable.您修改lnode ,这是一个局部变量。 You don't write this variable to anywhere else, so at the end of the function your modified object will be deleted.您不会将此变量写入其他任何地方,因此在函数结束时,您修改的对象将被删除。 Unless lnode is a handle object, in which case, by modifying it, you modify some global value somewhere that is also referenced by other local variables.除非lnode是一个句柄对象,在这种情况下,通过修改它,您可以在某个地方修改一些全局值,该值也被其他局部变量引用。

In MATLAB, everything is passed by value.在 MATLAB 中,一切都是按值传递的。 You should always think of variables inside your function as containing copies to the data passed in. Sometimes these values are handles to data elsewhere, in which case it'll appear as if the variable was passed by reference, but in effect you passed a copy of the handle.您应该始终将函数中的变量视为包含传入数据的副本。有时这些值是其他地方数据的句柄,在这种情况下,它看起来好像变量是通过引用传递的,但实际上您传递了一个副本的手柄。

A handle object is an instantiation of a handle class, a user-defined class that inherits from handle .句柄对象是句柄类的实例化,句柄类是继承自handle的用户定义类。 All copies of such an object point to the same data (in effect share data), so modifying one copy will modify all other copies as well.这种对象的所有副本都指向相同的数据(实际上是共享数据),因此修改一个副本也会修改所有其他副本。

You can write a function that does in-place modifications to its input by making the output variable name the same as an input variable name, only modifying that variable (rather than assigning a new value to it), and calling this function with the same variable as input and output.您可以编写一个对其输入进行就地修改的函数,方法是使输出变量名称与输入变量名称相同,仅修改该变量(而不是为其分配新值),并使用相同的方法调用此函数变量作为输入和输出。 For example:例如:

v = ones(10);
v = f(v);

function x = f(x)
x(1) = 0;
end

What this does is skip the copy of the matrix v , which would otherwise be made inside a function that modifies its inputs.这样做是跳过矩阵v的副本,否则它将在修改其输入的函数中生成。 In this case the copy can be avoided because the original matrix won't exist any more after the function call.在这种情况下,可以避免复制,因为在函数调用之后原始矩阵将不再存在。 So the in-place operation is an optimization of the interpreter, not a language feature.所以就地操作是对解释器的优化,而不是语言特性。 The final result would be identical if a copy were made (which is in fact what happened with that code prior to 2015 or whenever this optimization was introduced).如果制作了副本,最终结果将是相同的(事实上,这就是 2015 年之前的代码或引入此优化时发生的情况)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM