这与this question有些相关,但并不完全相同。
我有两个班级,FunctionWrapper
和TimerWrapper
:
classdef FunctionWrapper < handle
methods
function Fcn(obj)
disp('FunctionWrapper.Fcn was called!');
end
end
end
classdef TimerWrapper < handle
properties
Timer
end
methods
function obj = TimerWrapper(other_object)
obj.Timer = timer;
set(obj.Timer, 'Period', 1);
set(obj.Timer, 'ExecutionMode', 'fixedSpacing');
set(obj.Timer, 'TimerFcn', @(event, data) other_object.Fcn);
end
function start(obj)
start(obj.Timer);
end
function stop(obj)
stop(obj.Timer);
end
function delete(obj)
disp('destructor called!');
delete(obj.Timer);
end
end
end
假设我在命令窗口中执行以下代码:
>> F = FunctionWrapper;
>> T = TimerWrapper(F);
>> clear T %# T's destructor not called
>> timerfind %# just to verify that no, the destructor was never called
Timer Object: timer-1
Timer Settings
ExecutionMode: fixedSpacing
Period: 1
BusyMode: drop
Running: off
Callbacks
TimerFcn: @(event,data)other_object.Fcn
ErrorFcn: ''
StartFcn: ''
StopFcn: ''
这里发生了什么?我知道需要手动删除timer
个对象,但我认为这将在TimerWrapper
的析构函数中处理。不使用Amro's ugly but straightforward workaround to overload the clear
command,是否有办法从工作区clear T
?此外,没有任何内容涉及T
,那么为什么存在对它的引用呢? (从不调用析构函数的事实暗示了这一事实。)这是否隐藏在计时器对象本身中?
答案 0 :(得分:2)
如果键入t = TimerWrapper; f = functions(t.Timer.TimerFcn); f.workspace(2)
,您将看到用于回调的匿名函数的工作空间包含对TimerWrapper
对象本身的引用。所以那里有一种循环引用,clear
没有找到它。
考虑到你如何设置,你可以通过显式调用析构函数然后调用T
来删除clear
(及其底层计时器对象)。
T.delete
clear T
clear
和delete
之间的差异让我感到困惑(无论如何)。如您所见,clear
未明确调用析构函数。它只是从工作区中删除名称 T
。因此T
及其基础计时器在此时仍然存在。如果它们不包含对仍然存在的东西的引用,那么MATLAB将正确删除T
,包括调用它的析构函数。实际上,由于计时器包含一个仍然存在的T
引用(在其回调中),因此不会删除计时器(以及T
)。
您可以使用timerfindall
找到它(尽管工作区中没有名称),如果您使用
tmrs = timerfindall;
delete(tmrs);
你会发现T
现已正常消失。
我不太确定这是一个错误,虽然我觉得它很混乱,clear
和delete
之间的区别可能会更好地记录下来。
至于解决方法,我没有发现明确调用delete
是一件很大的痛苦,尽管如果你不小心打电话给clear
,清理一下会有点痛苦。我认为你链接到thread的消息#5中的建议,而不是消息#4,会更加通用和健壮。
我认为你不应该在你链接到的单独主题中以@Amro suggests的方式重载clear
:虽然如果你明确地调用clear T
这可能会有效,但你可以如果您拨打clear all
或clear variables
,仍会遇到麻烦。 (我刚才没有尝试过,但我相信clear
的这些语法甚至不会循环工作区中的内容并在每个上调用clear
- 而是调用clear
内部MATLAB工作空间对象的方法,这将很快混淆。)
答案 1 :(得分:0)
好像这可能是因为计时器的回调设置为非默认值。 A proposed workaround(参见链接线程的消息#4)仅在调用start
方法时设置回调函数,然后在调用stop
方法时将其设置为null。 / p>