Pass variable by reference to function

221 visualizaciones (últimos 30 días)
Adam
Adam el 28 de Sept. de 2012
Editada: Bart McCoy el 7 de Dic. de 2021
I have read that the only way to pass by reference with a function is if you pass a handle. Is there a matlab call to get the "handle" of a variable or structure?

Respuesta aceptada

Daniel Shub
Daniel Shub el 1 de Oct. de 2012
While I think IA's answer is the better way to do it. If you really want to do what you are talking about you can create a subclass of handle.
classdef myClass < handle
properties
data
end
methods
function h = myClass(data)
h.data = data ;
end
end
end
Then defining a function (which could be a method) like
function myFunction(h)
h.data = h.data+2;
end
lets you do something like
h = myClass(0);
myFunction(h);
h.data
ans =
2
of course things like h+2 will not work unless you implement a plus method.
  4 comentarios
Nick Dawson
Nick Dawson el 27 de Mzo. de 2021
Could I ask you why global variables aren't best practice?

Iniciar sesión para comentar.

Más respuestas (6)

Image Analyst
Image Analyst el 29 de Sept. de 2012
For all practical purposes, you can get the same effect by passing the input argument back out. For example, in the function definition:
function myVariable = ChangeMyVariable(myVariable)
myVariable = 2 * myVariable;
Then to call it, do this:
myVariable = ChangeMyVariable(myVariable);
And, obviously, myVariable could be anything, such as a structure like you mentioned. For all intents and purposes, this is the same as the code you'd use if it were pass by reference:
ChangeMyVariable(myVariable);
The net effect is you get your variable changed, it's just slightly different syntax.
  18 comentarios
Royi Avital
Royi Avital el 22 de Feb. de 2015
Hi, I tried your trick with very large matrix. By the jump in the memory consumption I can assure you it is not working by reference.
per isakson
per isakson el 22 de Feb. de 2015
I think there is a typo in the comment by Titus Edelhofer, it should read
var = someFun(x, var, y),
rather than
var = someFun(x, Var, y),
@Royi, Which release are you running?

Iniciar sesión para comentar.


per isakson
per isakson el 28 de Sept. de 2012
Editada: per isakson el 28 de Sept. de 2012
No, there is no way to pass a variable by reference. See Memory Management for Functions and Variables.
  2 comentarios
Adam
Adam el 28 de Sept. de 2012
I understand that only handles can be passed by reference. Is there a way of obtaining a handle for a variable?
per isakson
per isakson el 28 de Sept. de 2012
Editada: per isakson el 28 de Sept. de 2012
No, not with documented Matlab. And not with http://undocumentedmatlab.com/ as far as I know.
Why do you want to pass by reference?

Iniciar sesión para comentar.


James Tursa
James Tursa el 29 de Sept. de 2012
I will ask again what others have already asked. Why do you want the "handle" to the variable? What advice we give you will depend on the answer to that question. FYI, by default MATLAB passes a shared data copy of the arguments to the function ... i.e., there is no data copy involved. So it is already efficient in that sense. But we really need to know what you are doing with the variable inside the function in order to best answer your question, and whether passing by "reference" makes sense for your application.
  9 comentarios
Walter Roberson
Walter Roberson el 20 de Mzo. de 2020
Uh, No, the C community does not typically believe that C should only be used for low-level things like kernels and drivers!
I started programming in C in the early 1980s, and I hung around in the C Usenet programming groups for... Must have been over 25 years, starting even before The Great Renaming (of Usenet), from before C was standardized, before C++ was invented. C continues to be considered a "live" language for general use.
Marc Vaillant
Marc Vaillant el 24 de Mzo. de 2020
I also spent a good amount of time programming in C. Not quite as far back. Through most of the 90s, later switched to C++, and spent time reverse engineering Objective C and C as part of the iOS jailbreak dev community in the late 2000s. I spent a lot of time hanging out in IRC channels including #C and ##C, and as I mentioned, their mission statement basically renounced C as an application programming language. I think most good C programmers--who are also not blindly religious about the language--are honest about there almost always being a better choice than C for application programming. There just isn't a rich enough standard library--nor well used enough third party library--for writing programs as quickly or stably as they can be written in C++. C is small and as such is best suited for the types of programs that must have small footprints. The standard library plus RAII in C++ means that you can write an entire major C++ application without every having to call new, delete, malloc, or free yourself, and pay basically no penalty. And if you do have to call new/delete, you can put it into a very lightweight container like unique_ptr and continue to have exception safety. In short, I think it would be hard to argue that building an application in C is better than building it in C++, other than for environments where optimizing footprint is paramount. And, nothing stops you from using a C library where needed in a C++ program. Heck, even compiling C code with a C++ compiler (which is more strict) would likely uncover hidden issues in your C code.

Iniciar sesión para comentar.


Alessandro
Alessandro el 16 de Abr. de 2013
Hello I would say a possible solution is the following (without using classes):
%Reference to some matlab Data
function reference = globaldata()
data = [];
reference = struct('GET',@GET,'SET',@SET);
function dataout = GET()
dataout = data;
end
function SET(datain)
data =datain;
end
end
I saw something like this for making linked lists in matlab on stack overflow.

Lamont Granquist
Lamont Granquist el 12 de Jun. de 2019
This isn't so much an answer but an example of why pass-by-reference would be useful. I want to pull an array of values out of an ode45 OutputFnc, the straightforward programming way to do this would be to create a closure over a local variable which was passed along with the function handle into ODE45 and have the OutputFnc update that. Since the original program is not the caller of the OutputFnc -- ode45 is -- it is not possible to use the output parameters.
T0a = [];
options = odeset('OutputFcn', @(t, y, flag) odethrust(t, y, flag, T0a, mf_bar, thrust_bar));
[t, y] = ode45(@(t, y) ode(t, y, tf0/2, thrust_bar, mf_bar, ve_bar), lgt, y0, options);
T0a
function dXdtau = ode(t, y, tau, thrust_bar, mf_bar, ve_bar)
r = y(1);
v = y(2);
m = y(3);
if m < mf_bar
T = 0;
else
T = thrust_bar;
end
drdt = v;
dvdt = - 1/r^2 + T / m;
dmdt = - T / ve_bar;
dXdtau = tau * [ drdt dvdt dmdt ]';
end
function status = odethrust(t,y,flag,T, mf_bar, thrust_bar)
if isempty(flag)
m = y(3);
if m < mf_bar
T = [ T 0 ];
else
T = [ T thrust_bar ];
end
end
status = 0;
end
That is a snippet out of a real program so some variables like mf_bar/ve_bar/thrust_bar/etc aren't declared. The structure of the ODE isn't terribly important other than I'm trying to access the time history of the T variable as well as the variables of integration (pretend that the simplistic way T is handled now could be arbitrarily complicated so I don't want answers that figure out the problem analytically outside of this loop -- if you can guess the problem domain, you can be sure I know that the rocket equation exists).
The important point is the way that I want to declare T0a as an empty array, and then pass that into the function handle of odethrust, which is the OutputFcn for the ode45 call.
I guarantee there's nothing wrong -- in a computer science sense -- with wanting to pass in a closure like this to accumulate state.

Bart McCoy
Bart McCoy el 7 de Dic. de 2021
Editada: Bart McCoy el 7 de Dic. de 2021
I've been using Handle classes for awhile now and they are as close to "pass by reference" as you can get in MATLAB. Whether it's truly "pass by reference" or not may be an academic debate because it looks & acts like a duck & acts like a duck, so....
When you create an instance of a handle class, you can still create many distinct, independent instances. But for each instance you create, there is only one copy of that instance, no matter how many times you store it, pass it into other objects where they store it, etc. When you change it in one location, it's changed in ALL locations because there is only one copy of that instance.
Some practical benefits:
  1. With a class method, you can modify an object's contents & you no longer have to return the object. No danger of stale objects.
  2. Once you create an instance & store it somewhere (inside other objects, structs, object arrays, etc), the instance exists until ALL reference to your instance are gone or until you run delete(instanceName)
  3. If your object stores lots of data, a handle class won't keep copying your data & bloating memory useage
  4. If you need to share an object/data with lots of items, such as a global settings or a common configuration, or if you have communication/messaging/flag variables shared between lots of objects, handle classes are a dream!! Create one instance and share it with all your objects & let them store it for their lifetime. Whenever some object's code/class/function updates the single instance, all objects instantly see the same updates.
Handle classes might be a bad idea if you want objects to be fluid & copied in math operations, using overloaded operators for math-like operations.... where you're expecting implicit copies of the object (in a right-hand side set of math operations) to act independently, but they are really the same object.
To make your custom class a "handle class", you simply change the first line in the class from:
% Normal, non-handle class; An object instance is pass by value; the
% instance (and all data within it) is copied everywhere
classdef myClass
% bla bla bla
end
% Handle class; An object instance acts like pass-by-reference;
% For each instance, there is only one copy; change it once and it changes
% everywhere
classdef myClass < handle
% bla bla bla
end
% EXAMPLE CLASS AND SOME TESTS I WROTE TO HELP CLARIFY
% Save as InventoryHC.m
classdef InventoryHC < handle
properties
apples = 0;
bananas = 0;
total = 0;
end
methods
function obj = InventoryHC()
end
function computeTotal(obj)
obj.total = obj.apples + obj.bananas;
end
end
end
% TEST CODE TO HELP UNDERSTAND HOW HANDLE CLASS WORKS
clear all; clc;
% ONE instance of a handle class
inv1 = InventoryHC();
inv1.apples = 20;
inv1.bananas = 30;
inv1
inv1.computeTotal(); % NOTICE!! The object changed and you didn't have to return the object!
inv1
% ANOTHER independent instance of a handle class
inv2 = InventoryHC();
inv2.apples = 100;
inv2.bananas = 300;
inv2.computeTotal(); % NOTICE!! The object changed and you didn't have to return the object!
inv2
inv1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Make copies of the instance "inv1" and show that
% changing them in one location changes them everywhere
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Assign instance "inv" to another varible
newInv = inv1;
% Create a structure and store the object in it
dataset1 = struct();
dataset1.A = inv1;
dataset1.B = newInv;
invArray = [ inv1 newInv ]; % Create an object array & store the instances in it
invCell = { inv1 newInv }; % Create a cell array & store the object instances
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Now change the original instance in one place and show that
% it changed EVERYWHERE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
inv1 % Before we change it
inv1.apples = -5; % Make changes
inv1.bananas = -6;
inv1.computeTotal();
inv1 % View changes to the original instance
newInv % View the copy of the instance (it's also been changed)
dataset1.A % Instances stored in the structure (it's also been changed)
dataset1.B
invArray(1) % Instances in the object array (they've been changed, too)
invArray(2)
invCell{1} % Instances in the cell array (they've been changed, too)
invCell{2}
clear inv1; % Clear the original var; it's not special; it has a reference to the instance, just like the structure, array & cell array
newInv % Object is still alive & well
dataset1.A % Object is still alive & well
clear newInv dataset1 % Clear the other var and the structure
invArray(1) % The same object still persists; it will continue to persist until:
% a) all references to it are gone so it can garbage collect
% -OR- b) you call delete() to explicitly delete it
isvalid(invArray(2)) % Show that we still have a valid handle
delete(invArray(2)); % Delete the 2nd element in the array... this wipes out the instance EVERYWHERE
isvalid(invArray(2)) % Show that the handle is no longer valid
invArray(1) % Now just have an empty handle... no object assigned to it anymore
invArray(2) % Now just have an empty handle... no object assigned to it anymore
invCell{1} % Now just have an empty handle... no object assigned to it anymore
invCell{2} % Now just have an empty handle... no object assigned to it anymore
inv2 % This is a distinct instance created by it's own constructor call, so it's not tied to inv1

Categorías

Más información sobre Functions en Help Center y File Exchange.

Productos

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by