Генератор кода статически определяет время жизни объекта указателя. Когда вы используете объекты указателя, этот статический анализ имеет определенные ограничения.
Со статическим анализом сгенерированный код может снова использовать память, а не полагаться на схему управления динамической памятью, такую как подсчет ссылок или сборка мусора. Генератор кода может избежать динамического выделения памяти и автоматического управления памятью во время выполнения. Эти характеристики сгенерированного кода важны для некоторых критических по отношению к безопасности и приложений реального времени.
Для ограничений см.:
Генератор кода анализирует, заданы ли все переменные до использования. Неопределенные переменные или типы данных вызывают ошибку во время генерации кода. При определенных обстоятельствах генератор кода не может определить, заданы ли ссылки, чтобы обработать объекты. Смотрите, что Ссылки, чтобы Обработать Объекты Могут Казаться Неопределенными.
Считайте класс Handle mycls
и функциональным usehandle1
. Генератор кода сообщает об ошибке, потому что p
, который является вне цикла, имеет свойство, которое относится к объекту mycls
, созданному в цикле.
classdef mycls < handle properties prop end end
function usehandle1 p = mycls; for i = 1:10 p.prop = mycls; end
Если персистентная переменная относится к объекту указателя, генератор кода позволяет только один экземпляр объекта в течение времени жизни программы. Объект должен быть одноэлементным объектом. Чтобы создать одноэлементный объект указателя, заключите операторы, которые создают объект в защите if isempty()
для персистентной переменной.
Например, считайте класс mycls
и функциональным usehandle2
. Генератор кода сообщает об ошибке для usehandle2
, потому что p.prop
относится к объекту mycls
, который создает оператор inner = mycls
. Этот оператор создает объект mycls
для каждого вызова usehandle2
.
classdef mycls < handle properties prop end end
function usehandle2(x) assert(isa(x, 'double')); persistent p; inner = mycls; inner.prop = x; if isempty(p) p = mycls; p.prop = inner; end
Если вы перемещаете операторы inner = mycls
и inner.prop = x
в защите if isempty()
, генерация кода успешно выполняется. Оператор inner = mycls
выполняется только однажды в течение времени жизни программы.
function usehandle2(x) assert(isa(x, 'double')); persistent p; if isempty(p) inner = mycls; inner.prop = x; p = mycls; p.prop = inner; end
Рассмотрите функциональный usehandle3
. Генератор кода сообщает об ошибке для usehandle3
, потому что персистентный переменный p
относится к объекту mycls
, который создает оператор myobj = mycls
. Этот оператор создает объект mycls
для каждого вызова usehandle3
.
function usehandle3(x) assert(isa(x, 'double')); myobj = mycls; myobj.prop = x; doinit(myobj); disp(myobj.prop); function doinit(obj) persistent p; if isempty(p) p = obj; end
Если вы делаете myobj
персистентным и заключаете оператор myobj = mycls
в защите if isempty()
, генерация кода успешно выполняется. Оператор myobj = mycls
выполняется только однажды в течение времени жизни программы.
function usehandle3(x) assert(isa(x, 'double')); persistent myobj; if isempty(myobj) myobj = mycls; end doinit(myobj); function doinit(obj) persistent p; if isempty(p) p = obj; end
Рассмотрите функциональный refHandle
, который копирует свойство объекта указателя в другой объект. Функция использует простой класс Handle и класс значения. В MATLAB® функция запускается без ошибки.
function [out1, out2, out3] = refHandle() x = myHandleClass; y = x; v = myValueClass(); v.prop = x; x.prop = 42; out1 = x.prop; out2 = y.prop; out3 = v.prop.prop; end
classdef myHandleClass < handle properties prop end end
classdef myValueClass properties prop end end
Во время генерации кода происходит ошибка:
Property 'v.prop.prop' is undefined on some execution paths.
Три переменные ссылаются на ту же ячейку памяти: x
, y
и v.prop
. Генератор кода решает, что x.prop
и y.prop
совместно используют то же значение. Генератор кода не может решить, что свойство объекта указателя v.prop.prop
совместно использует свое определение с x.prop
и y.prop
. Чтобы избежать ошибки, задайте v.prop.prop
непосредственно.