For a while now I have been reading the documentation, for Visual C++ 2005, in an attempt to migrate from native code to managed. I find it hard to understand how to use the different types, and what the equvivalent in native code is. Look at this code:
ref
class rc{};value class vc{};
f1(rc^ c1){}
f2(rc^% c1){}
is
rc^ myrc = gcnew rc;
equvivalent to
rc * myrcN = new rc;
in native code And is "Handle to Object on Managed Heap" the same as "Pointer to Object" What is the difference of ref and value If i want a object on managed heap do I use the "ref" keyword, and value keyword if I want it on the stack An if so, why can I do this:
vc^ c = gcnew vc; // value object on managed heap
And where does this object go:
rc r; // ref object on stack
When am I supposed to use value and when am I supposed to use ref Is ref used for objects that are using dynamic allocated memory, and value classes used when an object is put on the stack
In f1() and f2() c1 is a handle to a rc object, but if a handle is the same as a pointer are the two function signatures allmost the same (pointer and ref to pointer)
When I pass a handle as an argument to a function does it get passed by copy or is it like passing a pointer Is it any difference in passing a value class and a ref class When do I use the "Tracking Reference (%)" in function signatures
Please help me... I a little bit confused here as you see. The documentation offers a little explanation but ont the other hand offers code, that for a newbie, is a little bit ambiguous... well not all code but in this are I have difficulty to grasp the concept.

Tracking Reference (%), value, ref??
Jayanthi
If I can add my 2 cents...
The first time I really had to use a tracking reference was when I had a method with an String out parameter.
fn1( String ^ str ) { str = L"Hello"; }This just doesn't work because the line
str = L"Hello";
Creates a completely new String (any modification to a string creates a completly new string). That operation isn't recorded by ^str.
But changing the function to
fn2( String ^% str ) { str = L"Hello"; }works because ^% str *does* points to the new string.
So
{ String ^ MyString = L"Initialised"; fn1(MyString); Console::WriteLine(MyString); fn2(MyString); Console::WriteLine(MyString); } Would output: Initialised HelloBecause after the call to fn1(), MyString still points to the old string that it did before the call to fn1().
The call to fn2() makes MyString point to the new string created inside fn2().
james swanson
Raj Parmar
I will look in to that, and keeping this thread open for a while...
Thanks for the tip! =)
Adebee
I have been looking att the links I have got, but I still don't understand the following things:
In what situations am I suppose to use value types, and in what situations am I suppose to use reference types What is the main difference
What do I gain in calling a function whit this signature:
void f1(obj^% o);
instead of this one:
void f2(obj^ o);
as far as I can see they both behave like this native one:
void f3(obj & o);
by that I mean that they all seem to be working with the object I pass to the function instead of a copy of it... I have now learned that a handle is not a pointer and a handle is a reference to a object on the managed heap while a pointer is only an address. But by this reasoning in f1(obj^% o) I would then send a reference by reference and what is that good for
Mish
Yes: this is a good definition - a tracking reference is completely analgous to a reference to a pointer (*&) in ISO/IEC C++.
I would say that the choice of whether this is a value-type or a reference type is up to you. My rule of thumb (and I would emphasis that this is mine and a rule-of-thumb) is that if the data I am trying to represent has less than 4 fields (or say 16 bytes) and the only methods associated with it are very simple then I would make it a value-type (a good example is something like Point, Size, etc.). As always my rule has exceptions but in general it works pretty well.
Does the choice matter The one thing to remember about value-types is that the CLR will 'blit' (bitwise copy) them so if you are not happy about this or it doesn't match your mental model of how your data will behave then you would be better off using a reference type. Note: the whole issue of boxing can be a mess - if you value-type has a method that modifies the data in your class and you are boxing the value-type then you need to be careful as calling the method on a boxed instance of the class will modify the copy and not the original instance.
The declaration looks fine the only thing I would change would to use something like:
int elementCount = GetElementCount();
array<element^>^ myElements = gcnew array<element^>(elementCount);
Pierre bzh
Nishant Sivakumar what do you mean by "one level of indirection is required" and what is "POD"
riz332
Marking this thread as answered. After reading existing literature which does cover all your questions, you can add more questions to this thread.
Further reading (from searching MSDN):
Managed classes and structs:
http://msdn2.microsoft.com/en-us/library/6w96b5h7(VS.80).aspx
Tracking references:
http://msdn2.microsoft.com/en-us/library/8903062a.aspx
David.Liu
Sending a reference by ref is useful if you want to allow the reference itself to change - i.e., you want the method to be able to redirect the reference to a different object.
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
Instant C++: C# to C++ converter and VB to C++ converter
Instant J#: VB to J# converter
Clear VB: Cleans up VB.NET code
Clear C#: Cleans up C# code
mshanzer
I think I am beginning to understand the tracking references now...
ref
class rc{private: int i;
public:
rc(int init){i = init;}
void add(void){ i++;}
void show(void){Console::WriteLine("i = {0}", i);}
};
void
setNew(rc^% refrc){refrc = gcnew rc(13);}void
useAdd(rc^ refrc){refrc->add();
refrc->show();
}
Because the function setNew() is altering the tracking handle it self, the argument need to be sent by reference. The useAdd() function is, by memberfunctions in the object, altering a member in the rc-object. The referencvariable here don't need to be sent by reference, because it is the object the reference is refering to that is about to be altered not the reference it self.
Have I got this right
If I have a class with an array containing elements of small structs like this one:
struct element{
UInt32 member1;
Byte member2;
UInt32 member3;
}
array<element^>^ myelements = gcnew array<element^>(5);
The number of elements in the array are determined when the application is running. The application reads different data from a xml-file depending on how the user interact with the program, hence the variation in length of myelements. Now for my questions:
Should the struct be of value type or ref type
Does it matter
How should the declaration, for the array, look like depending on the type i choose
prashant
Tracking references are the managed equivalent of native references. See http://blog.voidnish.com/ p=43 for an example of why they are required.
Value types are used where you don't need the overhead of a Reference type (where to access the object, one level of indirection is required, as well as additional GC overheads). In general, you can think of using Value types whenever a type behaves in a POD manner.
lalit_2007
Exactly: when you box a value-type like:
vc^ heapvaluetype = valuetype;
The CLR allocates the necessary memory on the heap then initializes it with a bitwise copy of the original instance. If you then call a modifying function on this boxed version, say:
heapvaluetype->add();
It will update the boxed version but not the original version.
John Bledsoe
See http://www.codeproject.com/managedcpp/cppcliintro01.asp
It introduces core C++/CLI concepts.
hsacks
By "boxing the value-type" i suppose you mean something like this:
value class vc {
int i;
vc(int number) { i = number; }
void add(){ i = i + 5; }
}
vc valuetype(12);
vc^ heapvaluetype = valuetype;
Is this the boxing you are talking about Is the trackinghandle in this case referenceing a copy of valuetype on the managed heap