constructor confusion

I

Ian

I was under the impression that the following produced the same IL code:
A ^a = gcnew A();
A a;

The first line creates object 'a' using gcnew while the second line creates
object 'a' using stack based code. I understood both methods produce the
same object - is this true? If not, what is the difference between the
objects created using gcnew and stack based code?

The lines numbered 6 to 11 below illustrate that the constructor called
depends upon the method used to create an object. Lines 5, 8 and 10 call
constructor #4 while lines 7, 9 and 11 call constructor #3. Given that
all objects are supposedly allocated on the managed heap, I expected only
constructor #4 would be called. Would someone kindly explain what is
happening here? Why does a 'pseudo' stack based object produce different
results than objects created using gcnew?

Thanks

Ian





ref class A
{
public:
A() { // ctor #1
iValue = 0;
};
A( const int i ) { // ctor #2
iValue = i;
}
A( const A% a ) { // ctor #3
iValue = a.iValue;
}
A( const A^ a ) { // ctor #4
iValue = a->iValue;
}

int iValue;
};

A ^a1 = gcnew A( 1 ); // (1) calls ctor #2
A a2 = gcnew A( 2 ); // (2) calls ctor #2
A a3( 2 ); // (3) calls ctor #2

A ^b1 = a1; // (4) ctor not called
A b2 = a1; // (5) calls ctor #4
//A ^b3 = a2; // (6) compiler error 2440
A b4 = a2; // (7) calls ctor #3

A ^c1 = gcnew A( a1 ); // (8) calls ctor #4
A ^c2 = gcnew A( a2 ); // (9) calls ctor #3
A c3 = gcnew A( a1 ); // (10) calls ctor #4
A c4 = gcnew A( a2 ); // (11) calls ctor #3
 
T

Tamas Demjen

Ian said:
I was under the impression that the following produced the same IL code:
A ^a = gcnew A();
A a;

Yes, when A is not IDisposable. If A is inherited from IDisposable (has
a user defined destructor), then

A a;

works more like this:

A^ a = gcnew A;
try
{
}
finally
{
delete a; // a->Dispose();
}
Given that
all objects are supposedly allocated on the managed heap, I expected only
constructor #4 would be called. Would someone kindly explain what is
happening here?

They are all allocated on the managed heap. It's just the syntax that's
different. A% is compiled to the same code as A^, just like A&
internally uses an A* pointer too. In C++, when you write

int x;
int& x_ref = x;
x_ref = 1;

it generates the same machine code as

int x;
int* x_ptr = &x;
*x_ref = 1;

Only the syntax is different.

The same is happening in C++/CLI, except replace & with %, and * with ^.

The syntax has nothing to do with the memory location of the object. Can
you say a C++ reference is always on the stack? Nope:
C* c = new C;
C& ref = *c; // it's still a heap object, not on the stack

This is exactly what's happening with the C++/CLI % syntax. It doesn't
mean that your class is no longer on the managed heap. In fact, a ref
class must always be allocated by gcnew, even if the syntax hides that.
The only difference between ^ and % is an operator*, nothing else.

ctor #3 is called when the source object has the stack syntax:
A one;
A two(one); // #3

and ctor #4 is called when the source has the handle syntax:
A^ one = gcnew A;
A two(one);

It's that simple. Both objects are on the managed heap, and both sample
code pieces generate essentially the same IL output.

Tom
 
B

Ben Voigt

Ian said:
I was under the impression that the following produced the same IL code:
A ^a = gcnew A();
A a;

The first line creates object 'a' using gcnew while the second line
creates object 'a' using stack based code. I understood both methods
produce the same object - is this true? If not, what is the difference
between the objects created using gcnew and stack based code?

The lines numbered 6 to 11 below illustrate that the constructor called
depends upon the method used to create an object. Lines 5, 8 and 10 call
constructor #4 while lines 7, 9 and 11 call constructor #3. Given that
all objects are supposedly allocated on the managed heap, I expected only
constructor #4 would be called. Would someone kindly explain what is
happening here? Why does a 'pseudo' stack based object produce different
results than objects created using gcnew?

Thanks

Ian





ref class A
{
public:
A() { // ctor #1
iValue = 0;
};
A( const int i ) { // ctor #2
iValue = i;
}
A( const A% a ) { // ctor #3
iValue = a.iValue;
}
A( const A^ a ) { // ctor #4
iValue = a->iValue;
}

int iValue;
};

A ^a1 = gcnew A( 1 ); // (1) calls ctor #2
A a2 = gcnew A( 2 ); // (2) calls ctor #2
A a3( 2 ); // (3) calls ctor #2

A ^b1 = a1; // (4) ctor not called
A b2 = a1; // (5) calls ctor #4 A b2b = ^a1; // calls ctor 3
//A ^b3 = a2; // (6) compiler error 2440
A b4 = a2; // (7) calls ctor #3 A b5 = %a2; // calls ctor 4

A ^c1 = gcnew A( a1 ); // (8) calls ctor #4
A^ c1b = gcnew A(^a1); // ctor 3
A ^c2 = gcnew A( a2 ); // (9) calls ctor #3
A^ c2b = gcnew A(%a2); // ctor 4
A c3 = gcnew A( a1 ); // (10) calls ctor #4
A c3b = gcnew A(^a1); // ctor 3
A c4 = gcnew A( a2 ); // (11) calls ctor #3
A c4b = gcnew A(%a2); // ctor 4
 
B

Ben Voigt

Ian said:
I was under the impression that the following produced the same IL code:
A ^a = gcnew A();
A a;

The first line creates object 'a' using gcnew while the second line
creates object 'a' using stack based code. I understood both methods
produce the same object - is this true? If not, what is the difference
between the objects created using gcnew and stack based code?

The lines numbered 6 to 11 below illustrate that the constructor called
depends upon the method used to create an object. Lines 5, 8 and 10 call
constructor #4 while lines 7, 9 and 11 call constructor #3. Given that
all objects are supposedly allocated on the managed heap, I expected only
constructor #4 would be called. Would someone kindly explain what is
happening here? Why does a 'pseudo' stack based object produce different
results than objects created using gcnew?

Overload resolution at work, same as native code:

void test(int&) { cout << "f"; }
void test(int*) { cout << "g"; }

int *pi = new int(0);
int &i = *pi; // same object

test(i); // f
test(pi); // g
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top