473,591 Members | 2,899 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

microsoft.publi c.dotnet.langua ges.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::WriteL ine("Should be 200 {0} EITHER WAY !: {1} ", y,
*y);

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

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

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

intRef = 21;
Console::WriteL ine("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::WriteL ine("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 8242
raylopez99 wrote:
microsoft.publi c.dotnet.langua ges.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...@yah oo.comwrote:
microsoft.publi c.dotnet.langua ges.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::WriteL ine("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::T oString 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::WriteL ine("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::WriteL ine("Should be intRef or 10: {0}...is it? (Yes!)",y);
See my explanation concerning the first WriteLine call....
>
intRef = 21;
Console::WriteL ine("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::WriteL ine("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...@yah oo.comwrote:
microsoft.publi c.dotnet.langua ges.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::WriteL ine("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::WriteL ine("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::WriteL ine("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********@yah oo.comwrote in message
news:11******** *************@f 1g2000cwa.googl egroups.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::WriteL ine("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::WriteL ine("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::WriteL ine("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********@yah oo.comwrote in message
news:11******** *************@f 1g2000cwa.googl egroups.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********@yah oo.comwrote in message
news:11******** *************@f 1g2000cwa.googl egroups.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*(Fract ion^ one, Fraction^ two) {
return gcnew Fraction(one->Numerator * two->Numerator,
one->Denominator * two->Denominator) ;
}
public Fraction% operator*(const Fraction% two) {
return Fraction(Numera tor * 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********@yah oo.comwrote in message
news:11******* **************@ f1g2000cwa.goog legroups.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
1613
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 ? or it doesn't ? Which are the potential problems I would have ? Do I lose portability ?
7
3875
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, decides to realloc memory that is not pinned, and that the unmanaged code's pointer becomes invalid. How often does the GC run, given a reasonably large app running on a P4 300ghz with over 1 gig ram? I would have thought that it did not need to...
0
826
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 appreciated. TIA
3
1216
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, Michele
5
1576
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 trying to have is a MVC-like scheme, where the view is implemented using Windows Forms and the model is composed of a bunch of previously-written non-managed C++ classes. That implies that the view (managed entity) will hold a reference to the model...
2
1439
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 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
11
4642
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 cli:array<cli::interior_ptr<float>, 2>... So, what do I do?
3
4839
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 pointers (delegates). I assume I need to use the array< T keyword to allocate an array of delegates, and then initialize the array by setting each array element to the pointers (handles) of the functions I'll be invoking. I've been trying to...
0
7935
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8236
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8227
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6642
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
5735
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5400
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3851
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
3893
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2379
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

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.