向量中的变量在调用堆栈返回后更改回来

时间:2013-10-28 19:11:54

标签: matlab vector

我在matlab中使用树中的递归调用,函数的基本结构在这里:

function recursion(tree, targetedFeatures)

    if (some conditions fulfilled)
      return;
    end

    for i = 1:1:size(targetedFeatures,2)
      .....
      .....
       if (some conditions that using index i is true)
          targetedFeatures(1,i) = 1; 
       end
    end

    if(tree has child nodes)
       recursion(tree.child(j).targetedFeatures)
    end
end

树的结构如下:

            root
           /  |  \
          /   |   \
         /    |    \
      leaf1  leaf2  leaf3

函数递归的输入参数是一个名为targetedFeatures的向量,假设它的初始值是[0 0 0],并且在访问leaf1的过程中,向量变为[1 0 0], BUT < / strong>访问leaf2时,targetedFeature 更改回[0 0 0]

我怀疑是因为matlab中的vector不喜欢其他编程语言中对象的引用?

如何避免此问题?感谢。

3 个答案:

答案 0 :(得分:2)

Matlab对正常类型的变量使用call-by-value,请参阅here。解决它的方法是让函数返回修改后的副本作为输出参数:

function targetedFeatures = recursion(tree, targetedFeatures)
  ...
  targetedFeatures = recursion(tree.child(j).targetedFeatures);
  ...
end

相反,可以使用evalin('caller', ...)inputname来模拟按引用调用。

答案 1 :(得分:1)

recursion函数需要修改targetedFeatures时,会创建targetedFeatures的副本,该副本对于该函数调用是本地的。如果您希望将更新传回给调用范围,则需要从函数中返回更新的targetedFeatures

function targetedFeatures = recursion(tree, targetedFeatures)

    if (some conditions fulfilled)
      return;
    end

    for i = 1:1:size(targetedFeatures,2)
      .....
      .....
       if (some conditions that using index i is true)
          targetedFeatures(1,i) = 1; 
       end
    end

    if(tree has child nodes)
       targetedFeatures = recursion(tree.child(j).targetedFeatures)
    end
end

这并不像使用C中的指针那样有效,但是你不应该看到代码已经在做什么的显着性能,因为你已经在更新时创建了本地副本targetedFeatures

感谢chappjc提供了this post的链接,该链接讨论了写时复制机制。

答案 2 :(得分:0)

根据树的长度和最终深度,上面基于回归的解决方案很快变得非常丑陋,因为你总是必须改变根节点,而原则上你只想改变许多叶子中的一个。

相反,您可能希望研究为TreeNode对象实现句柄类。 这将从一些简单的事情开始:

classdef TreeNode < handle

    properties
        targetedFeatures;
        child; % vector keeping handles to TreeNode children
        parent; % handle of the parent node, of which this node is a child
    end

    methods
        ...
    end
end

你显然必须填写添加/删除孩子等的方法。 使用这样的树,您可以递归到最深的叶子并更改其值,而无需始终携带对顶级根节点的引用。 一旦你有了这个,你应该能够使用你的功能而无需修改。

有点类似的类的实现是链表的实现,在MATLAB文档中演示: http://www.mathworks.de/de/help/matlab/matlab_oop/example--implementing-linked-lists.html 这里每个节点都有一个前一个和下一个“子”,而不是父节点和多个子节点,但是一般结构非常相似。

如果您计划在此树上进行大量其他操作,例如添加/删除节点,搜索等,那么在某些时候它肯定是值得的。 如果您碰巧碰到了那棵树,并且一旦解决了这个问题就完成了,那就去找基于回报的解决方案了。