473,395 Members | 1,568 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

What's with the new C++/CLI pointers (handles ^)? Managed C++.NET

microsoft.public.dotnet.languages.vc

Please comment on the following code fragment. Note the comments
"Why"?

Particularly,
(1) why does referencing and dereferencing a pointer give the same
thing (at least in WriteLine(), which might be some sort of cast going
on behind the scenes),
(2) why doesn't the pointer "stick to" a reference, such as when y =
intRef; below, then intRef is changed but the y handle does not change,
and
(3) why doesn't y = &intVT compile?

Thanks

RL

///////////////////////////////////////////////////////////////
// in managed C++/CLI console mode, using Visual Studio 2005, C++.NET

int intVT = 10;
int %intRef = intVT;
int ^y = gcnew int(200);
Console::WriteLine("Should be 200 {0} EITHER WAY !: {1} ", y,
*y);

*y = 210; //also works y = 210; //WHY y, *y same?

Console::WriteLine("Should be 210 {0}...is it? (Yes!)",*y);

y = intRef;
Console::WriteLine("Should be intRef or 10: {0}...is it?
(Yes!)",y);

intRef = 21;
Console::WriteLine("Should be intRef or 21: {0} , {1}...is it?
(NO!)",y, intRef); //WHY NOT?

y = intRef; //but now it should work: add-- y = intRef; // also
works:
*y = intRef; // same answer of 21! //Why same answer (why y, *y same)?

Console::WriteLine("Should be intRef or 21: {0} , {1}...is it?
(Yes!)",y, intRef);

//y = &intVT; //unsafe operation by definition? (NO, illegal!
Won't compile!)
//Why won't compile?
// EOF
/////////////////////////////////////////////////////////////////////////////////

Dec 19 '06 #1
9 8236
raylopez99 wrote:
microsoft.public.dotnet.languages.vc

Please comment on the following code fragment. Note the comments
"Why"?

Particularly,
(1) why does referencing and dereferencing a pointer give the same
thing (at least in WriteLine(), which might be some sort of cast going
on behind the scenes),
Because there's no way to "see" the value of a tracking pointer. Rather,
referring to a tracking pointer variable by name will impliciutly
dereference the pointer, just like referring to an ordinary C++ reference
would.
(2) why doesn't the pointer "stick to" a reference, such as when y =
intRef; below, then intRef is changed but the y handle does not
change,
and
Because a tracking pointer always points to an object in the managed heap.
When y = intRef is executed, the current value of intVT is boxed and placed
on the gc heap and y is set to reference that boxed copy.
(3) why doesn't y = &intVT compile?
Because a tracking pointer always points to an object in the managed heap.
intVT is not on the managed heap, so an int^ can't point to it.

-cd
Dec 19 '06 #2


On 19 déc, 12:10, "raylopez99" <raylope...@yahoo.comwrote:
microsoft.public.dotnet.languages.vc
See comments inline
///////////////////////////////////////////////////////////////
// in managed C++/CLI console mode, using Visual Studio 2005, C++.NET

int intVT = 10;
int %intRef = intVT;
Here we have a tracking reference that is "pointing" to a local
variable (on the stack)
int ^y = gcnew int(200);
Console::WriteLine("Should be 200 {0} EITHER WAY !: {1} ", y, *y);
When passing y to WriteLine, you are passing a handle to an object that
is on the garbage-collected heap (an Int32^). Since Int32 implements
IFormattable, WriteLine will call IFormattable::ToString on this
object.
When passing *y to WriteLine, you are implcitely unboxing the object,
and therefore passing an int to WriteLine, who knows how to handle it.

*y = 210; //also works y = 210; //WHY y, *y same?
y=210 works because there will be no meaning in changing the value of a
handle (remember, in .NET, handles are OPAQUES : there is no way to
assign them directly a value as you can do with pointers). In that
case, the compiler chooses the alternate interpretation instead of
spiting an error. I would say this choice is debatable, but this is how
things are....
>
Console::WriteLine("Should be 210 {0}...is it? (Yes!)",*y);

y = intRef;
Here is the danger! Since y is an Int32^, it can only "points" to
object on the managed heap. This line implicitely boxes the intRef
value : An In32 is gcnew-ed on the the managed heap and is assigned the
intRef value. This is a COPY of the original value. See "Implicit
boxing" in MSDN for more details.

Console::WriteLine("Should be intRef or 10: {0}...is it? (Yes!)",y);
See my explanation concerning the first WriteLine call....
>
intRef = 21;
Console::WriteLine("Should be intRef or 21: {0} , {1}...is it? (NO!)",y, intRef); //WHY NOT?
See above : y points to a COPY of intRef.
>
y = intRef; //but now it should work: add-- y = intRef; // also works:
Here again, since "y" has no possible meaning, the compiler interprets
it as "µy" (which I feel is dubious)
*y = intRef; // same answer of 21! //Why same answer (why y, *y same)?

Console::WriteLine("Should be intRef or 21: {0} , {1}...is it?(Yes!)",y, intRef);

//y = &intVT; //unsafe operation by definition? (NO, illegal! Won't compile!)
//Why won't compile?
A handle must "point" to an object on the garbage-collected heap, so
it can't be assigned the address of a stack object.

Arnaud
MVP - VC

Dec 19 '06 #3
Excellente! I appreciate it very much, both of the replies, and will
try and live within the confines of handles, garbage collection and
whatever else C++.NET throws my way (until I get fed up with it; I'm
also learning C#.NET, which seems a bit more simple/simplistic).
RL
ad******@club-internet.fr wrote:
On 19 déc, 12:10, "raylopez99" <raylope...@yahoo.comwrote:
microsoft.public.dotnet.languages.vc
Dec 19 '06 #4
The reason:
int ^y;
y = xyz;
*y = xyz;

work the same way is: they don't!

Microsoft has provided default definitions (for all built-in types) of:
int^ operator= (int^%, int^)
int operator= (int%, int)
and implicit boxing of the right-hand side...

But I think you'll find that:
int ^x = 1;
int ^y = 1;
^y = 2; // places 2 in the box referenced by y, changing also x
y = 3; // boxes 3, makes y point to it, leaving x pointing to boxed 2

Also, for user-defined types you can actually define those very differently.
To overload the handle operators, you have to use a static member function,
while for normal C++ operators, you can use a static member, instance
member, or friend function. On second thought, I'm not sure you can
redefine operator= on handle types, but you definitely can make the
arithmetic operators act differently for handles vs non-handles.
Dec 20 '06 #5
Thanks Ben for your input, but I just compiled your suggested code and
found a few mistakes (see below).

Ray

////////////////

// from the net:

int ^x = 1;
int ^y = 1;
Console::WriteLine("x, y are one,one: {0}, {1} ", *x, *y); //gives
output 1,1
*y = 2; // not ^y=2; places 2 in the box referenced by y, changing
also x [not true, x is not changed but remains one]
Console::WriteLine("x, y now two are one,two: {0}, {1} ", *x, *y);
//gives output 1,2
y = 3; // boxes 3, makes y point to it, leaving x pointing to boxed 2
[Not true, x points to 1]
Console::WriteLine("x, y are three: {0}, {1} ", *x, *y); //gives output
1,3, as expected

//////////////////

==
Ben Voigt wrote:
The reason:
int ^y;
y = xyz;
*y = xyz;

work the same way is: they don't!

Microsoft has provided default definitions (for all built-in types) of:
int^ operator= (int^%, int^)
int operator= (int%, int)
and implicit boxing of the right-hand side...

But I think you'll find that:
int ^x = 1;
int ^y = 1;
^y = 2; // places 2 in the box referenced by y, changing also x
y = 3; // boxes 3, makes y point to it, leaving x pointing to boxed 2

Also, for user-defined types you can actually define those very differently.
To overload the handle operators, you have to use a static member function,
while for normal C++ operators, you can use a static member, instance
member, or friend function. On second thought, I'm not sure you can
redefine operator= on handle types, but you definitely can make the
arithmetic operators act differently for handles vs non-handles.
Dec 21 '06 #6

"raylopez99" <ra********@yahoo.comwrote in message
news:11*********************@f1g2000cwa.googlegrou ps.com...
Thanks Ben for your input, but I just compiled your suggested code and
found a few mistakes (see below).
Yup, I don't always think right.

The part about matching different operator overrides is definitely true
though. For some class I ended up having to define both sets.
Ray

////////////////

// from the net:

int ^x = 1;
int ^y = 1;
Console::WriteLine("x, y are one,one: {0}, {1} ", *x, *y); //gives
output 1,1
*y = 2; // not ^y=2; places 2 in the box referenced by y, changing
also x [not true, x is not changed but remains one]
Console::WriteLine("x, y now two are one,two: {0}, {1} ", *x, *y);
//gives output 1,2
y = 3; // boxes 3, makes y point to it, leaving x pointing to boxed 2
[Not true, x points to 1]
Console::WriteLine("x, y are three: {0}, {1} ", *x, *y); //gives output
1,3, as expected

//////////////////

==
Ben Voigt wrote:
>The reason:
int ^y;
y = xyz;
*y = xyz;

work the same way is: they don't!

Microsoft has provided default definitions (for all built-in types) of:
int^ operator= (int^%, int^)
int operator= (int%, int)
and implicit boxing of the right-hand side...

But I think you'll find that:
int ^x = 1;
int ^y = 1;
^y = 2; // places 2 in the box referenced by y, changing also x
y = 3; // boxes 3, makes y point to it, leaving x pointing to boxed 2

Also, for user-defined types you can actually define those very
differently.
To overload the handle operators, you have to use a static member
function,
while for normal C++ operators, you can use a static member, instance
member, or friend function. On second thought, I'm not sure you can
redefine operator= on handle types, but you definitely can make the
arithmetic operators act differently for handles vs non-handles.

Dec 22 '06 #7
Thanks Ben. I'm sure even thinking non-right you're way ahead of me,
since I only play around with programming for fun...right now I'm
playing around with a demonstration program using the 'this' pointer
and using it to instantiate another composition class that's also a
friend (just to see what's different, if anything, between C++ and
C++.NET/CLI 2005 version).

Feel free to post an example of "matching different operator overrides
is definitely true .... For some class I ended up having to define
both sets." (operator overides use the 'this' pointer so it will be a
good example for my purposes).

RL

Ben Voigt wrote:
"raylopez99" <ra********@yahoo.comwrote in message
news:11*********************@f1g2000cwa.googlegrou ps.com...
Thanks Ben for your input, but I just compiled your suggested code and
found a few mistakes (see below).

Yup, I don't always think right.

The part about matching different operator overrides is definitely true
though. For some class I ended up having to define both sets.
Dec 22 '06 #8

"raylopez99" <ra********@yahoo.comwrote in message
news:11*********************@f1g2000cwa.googlegrou ps.com...
Thanks Ben. I'm sure even thinking non-right you're way ahead of me,
since I only play around with programming for fun...right now I'm
playing around with a demonstration program using the 'this' pointer
and using it to instantiate another composition class that's also a
friend (just to see what's different, if anything, between C++ and
C++.NET/CLI 2005 version).

Feel free to post an example of "matching different operator overrides
is definitely true .... For some class I ended up having to define
both sets." (operator overides use the 'this' pointer so it will be a
good example for my purposes).
Again, not compiled so you may have to tweak it a bit:

ref struct Fraction
{
int Numerator, int Denominator;

public Fraction(int num, int denom) { /* reduces fraction, etc. */ }

public static Fraction^ operator*(Fraction^ one, Fraction^ two) {
return gcnew Fraction(one->Numerator * two->Numerator,
one->Denominator * two->Denominator);
}
public Fraction% operator*(const Fraction% two) {
return Fraction(Numerator * two.Numerator, Denominator *
two.Denominator);
}
};

client code:
void TestIt()
{
Fraction a, b; // erm, C# needs = new Fraction() added here
a.Numerator = 1;
a.Denominator = 3;
b.Numerator = 2;
b.Denominator = 7;
Fraction product = a * b; // C# and C++/CLI call different operators!
// In fact, C++/CLI has to
call the copy constructor as well
}

C++ code that acts like C#:
void TestIt()
{
Fraction^ a = gcnew Fraction();
Fraction^ b = gcnew Fraction();
a->Numerator = 1;
a->Denominator = 3;
b->Numerator = 2;
b->Denominator = 7;
Fraction^ product = a * b; // Calls the same operator* as C# does
}
>
RL

Ben Voigt wrote:
>"raylopez99" <ra********@yahoo.comwrote in message
news:11*********************@f1g2000cwa.googlegro ups.com...
Thanks Ben for your input, but I just compiled your suggested code and
found a few mistakes (see below).

Yup, I don't always think right.

The part about matching different operator overrides is definitely true
though. For some class I ended up having to define both sets.

Dec 22 '06 #9
Thanks; this will be my next demo project. Today I learned
Delegates/Events (like function pointers/ templates but a little
different) in managed C++/CLI, and found out much to my chagrin no
friend functions exist (but no problem, just declare and use a public
interface between the friendly classes; a bit ackward but no big deal).

RL
Ben Voigt wrote:
Feel free to post an example of "matching different operator overrides
is definitely true .... For some class I ended up having to define
both sets." (operator overides use the 'this' pointer so it will be a
good example for my purposes).

Again, not compiled so you may have to tweak it a bit:

ref struc
Dec 23 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Craig Kenisston | last post by:
Which are the disadvantage of use pointers in the code ? In general. I know it turns your code into unsafe code, because even you have to flag it ... but does it still 100% managed code, right...
7
by: _BNC | last post by:
Another thread mentioned non-Pinned pointers as a possible reason for an Interop bug. I'd like to find out more about how this comes about. I presume that the Garbage Collector makes a sweep,...
0
by: Lev | last post by:
Hi, How do you store a pointer to an unmanaged class in a managed class such that it will not get corrupted? I have tried declaring the pointer __nogc* but it doesn't seem to work. Any ideas are...
3
by: m | last post by:
Hi, I'm reading Microsoft Visual C++ .NET Step by Step, Version 2003 and I found a sentence it says : "you can't have pointers to managed types as members of a __gc class.". Why ? Thanks,...
5
by: Ney André de Mello Zunino | last post by:
Hello. I am developing a project in managed C++ for the first time. Things were going fine up until the point I had the need to mix managed and non-managed code. More specifically, what I am...
2
by: raylopez99 | last post by:
Please comment on the following code fragment. Note the "WHY"? Particularly, (1) why does referencing and dereferencing a pointer give the same thing (at least in WriteLine(), which might be some...
11
by: memeticvirus | last post by:
I have an array cli::array<float, 2and I would like to access a subset of it's values by compiling an array of pointers. But, it's not possible to create an array of type...
3
by: David K in San Jose | last post by:
I'm using managed (CLR) C++ in VS2005 to create a Windows app that contains a form named "MyForm". In the code for that form I'm trying to invoke some static functions by using an array of function...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.