VMatrix &f1( void ) { VMatrix b("local mat",5,5); return b; } VMatrix &f2( void ) { VMatrix *b = new VMatrix("local mat",5,5); return *b; } main() { VMatrix c; c= f1() + f2(); }This code won't work. The call to f1() attempts to return a local matrix. However, C++ calls the destructor of b before returning, so the returned reference points to an abandonded location in the program stack, and hence to garbage. The call to f2() does not quite solve the problem of f1(). It returns a valid reference to a matrix, but the reference is lost once the equal sign is processed in the main function. It is lost in the sense that no variable contains the reference, so it cannot be removed from the heap. If you call f2() too often, the heap will fill up and the program will crash. Both of these problems are solved by the stack. The solution is to store a copy of the matrix in the stack, which is a global data structure. The correct program above then is
#include "virt.h" MStack *Dispatch = new MStack; VMatrix &f1( void ) { VMatrix b("local mat",5,5); Dispatch->Push(b); return Dispatch->ReturnMat(); } VMatrix &f2( void ) { VMatrix *b = new VMatrix("local mat",5,5); Dispatch->Push(*b); delete b; return Dispatch->ReturnMat(); } main() { VMatrix c; c= f1() + f2(); vclose(); }This program will work as long as you do not need to control the function nesting level. The next example shows how you can use the function nesting level to use matrix assignment in all functions.
#include "virt.h" MStack *Dispatch = new MStack; VMatrix &f1( void ) { VMatrix b = Fill(5,5,1); b.Nameit("Local"); Dispatch->Push(b); return Dispatch->ReturnMat(); } VMatrix &f2( void ) { Dispatch->Inclevel() VMatrix *b = new VMatrix; *b = Fill(5,5,2); b->Nameit("pointer"); Dispatch->Push(*b); delete b; return Dispatch->Decreturn(); } VMatrix &f3( void ) { Dispatch->Inclevel(); VMatrix b = f1() + f2(); Dispatch->Push(b); return Dispatch->DecReturn(); } main() { VMatrix c = f1() + f3() + f2(); vclose(); }Note that a matrix assignment is used in f3(). The stack is cleared of intermediate matrices when using matrix assignment by calling CleanStack(). The matrix nesting level index is used to determine which matrices are to be removed from the stack. When f3() is called, f2() has already been called in main(), so the stack has the result of f2() in it. This copy will not be erased when f3() calls the equals operator because the nesting level is incremented at the function entry. Only the results on the stack created while f3() is active are popped off the stack. Thus the first copy of f2() in main() are preserved.
The difference between Dispatch->ReturnMat() and Dispatch->DecReturn() is that DecReturn decrements the matrix nesting level and ReturnMat() does not. You use ReturnMat() if you did not need matrix assignment in a function, and hence did not call Inclevel() at the top. You use DecReturn() if you needed to use matrix assignment hence called Inclevel() at the top.
I chose the word Dispatch for the stack root to suggest that "messages" may be sent to the stack through the stack dispatcher. The stack should be declared in the global data area as a pointer. This is expected throughout the program.