MATLAB Answers

Pass variable by reference to function

652 ビュー (過去 30 日間)
Adam
Adam 2012 年 9 月 28 日
コメント済み: Marc Vaillant 2020 年 3 月 24 日
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?

  0 件のコメント

サインインしてコメントする。

採用された回答

Daniel Shub
Daniel Shub 2012 年 10 月 1 日
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.

  2 件のコメント

Alessandro
Alessandro 2013 年 2 月 27 日
Nice post ! Matlab should have something like this as a standard object ! The problem with this class is that it still copy the value from workspace to the class but is a good workaround.
Nicholas Ayres
Nicholas Ayres 2020 年 3 月 18 日
Alternatively, making your variable a global before calling and set your variable as global before updating it in your function.
global variables are not best practice, but this would still work.

サインインしてコメントする。

その他の回答 (5 件)

Image Analyst
Image Analyst 2012 年 9 月 29 日
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 件のコメント

表示 15 件の古いコメント
Titus Edelhofer
Titus Edelhofer 2015 年 1 月 8 日
Hi Lucas,
the programming pattern that Image Analyst showed, namely
function Y = someFun(x, Y, z)
Y = x + Y;
involves no copying of Y at all, provided, that you
  • call it like var = someFun(x, var, y), i.e. both the function declaration and the calling function use the same variable names for input and output
  • Your MATLAB version is not too old: this optimization was introduced somewhere around 2010.
Give it a try with a large variable. You will see in the task manager no copy is done.
Titus
Royi Avital
Royi Avital 2015 年 2 月 22 日
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 2015 年 2 月 22 日
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?

サインインしてコメントする。


per isakson
per isakson 2012 年 9 月 28 日
編集済み: per isakson 2012 年 9 月 28 日
No, there is no way to pass a variable by reference. See Memory Management for Functions and Variables.

  2 件のコメント

Adam
Adam 2012 年 9 月 28 日
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 2012 年 9 月 28 日
No, not with documented Matlab. And not with http://undocumentedmatlab.com/ as far as I know.
Why do you want to pass by reference?

サインインしてコメントする。


James Tursa
James Tursa 2012 年 9 月 29 日
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 件のコメント

表示 6 件の古いコメント
Marc Vaillant
Marc Vaillant 2020 年 3 月 20 日
Thanks, good point about legacy C code. The reality though is that C shouldn't be used for programming beyond low level stuff like kernels and drivers. The C programming community typically subscribes to this point of view (as I recall the #C freenode IRC channel had a statement to that effect in their channel description). I know Linux Torvalds doesn't like C++, but the reality is that if you use it right and don't try to use extended features that tend to make your code obfuscated, it keeps you from shooting yourself in the foot, particularly with respect to memory management. I wouldn't touch a piece of code that didn't subscribe to proper const correctness. Having said all that, I have recently used Darknet, a deep neural network framework written in C which was refreshingly stripped down and extremely portable because it didn't have any dependencies besides CUDA. Ultimately, that implementation is just too dangerous to use in production, and not flexible enough for all environments (like CPU deployment).
Walter Roberson
Walter Roberson 2020 年 3 月 20 日
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 2020 年 3 月 24 日
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.

サインインしてコメントする。


Alessandro
Alessandro 2013 年 4 月 16 日
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.

  0 件のコメント

サインインしてコメントする。


Lamont Granquist
Lamont Granquist 2019 年 6 月 12 日
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.

  0 件のコメント

サインインしてコメントする。


Translated by