By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,314 Members | 1,751 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,314 IT Pros & Developers. It's quick & easy.

Rationale for C++/CLI Value Types not having a default constructor

P: n/a
Given

value class X
{
public:
// Not allowed: X():i(100000),s(10000) { }
// Allowed
void InitializeDefaults() { i = 100000; s = 10000; }
private:
int i;
short s;
}

How can:

1)

X x;
x.InitializeDefaults();

be better semantically than

2)

X x;

for setting the default values of 100000 for i and 10000 for s ? In
other words what is the rationale for removing the natural user-defined
default constructor for value types and forcing the user to default
construct the value type object to its zero or null values and then have
to call another function to set default values which the type may want ?
I read that 2) can not be guaranteed to occur properly but 1) evidently
can ? Someone please explain to me how a sequence of two syntax actions
has a better guarantee of properly being implemented than just one.
Apr 25 '06 #1
Share this Question
Share on Google+
12 Replies


P: n/a
for setting the default values of 100000 for i and 10000 for s ? In
other words what is the rationale for removing the natural user-defined
default constructor for value types and forcing the user to default
construct the value type object to its zero or null values and then have
to call another function to set default values which the type may want ?


<from http://www.codecomments.com/archive292-2006-2-806923.html>

If you also look in "C++-CLI Standard.pdf", you read :

12.2.1 Value classes
A value class is a data structure that contains fields, function members,
and nested types. Unlike other class
types, value classes do not support user-defined destructors, finalizers,
default constructors, copy
constructors, or copy assignment operators. Value classes are designed to
allow the CLI execution engine to
efficiently copy value class objects.

--

Kind regards,
Bruno van Dooren
br**********************@hotmail.com
Remove only "_nos_pam"
Apr 26 '06 #2

P: n/a
Edward Diener wrote:
Given

value class X
{
public:
// Not allowed: X():i(100000),s(10000) { }
// Allowed
void InitializeDefaults() { i = 100000; s = 10000; }
private:
int i;
short s;
}

How can:

1)

X x;
x.InitializeDefaults();

be better semantically than

2)

X x;

for setting the default values of 100000 for i and 10000 for s ? In
other words what is the rationale for removing the natural
user-defined default constructor for value types and forcing the user
to default construct the value type object to its zero or null values
and then have to call another function to set default values which
the type may want ? I read that 2) can not be guaranteed to occur
properly but 1) evidently can ? Someone please explain to me how a
sequence of two syntax actions has a better guarantee of properly
being implemented than just one.


It's simple: The CLR expects to be able to default-construct a value type
by 0-filling it's representation and cannot guarantee that a constructor
will be called.

-cd
Apr 26 '06 #3

P: n/a
That's a strange story. .NET's base spec (the Common Langauge
Infrastructure) does support value types with parameterless constructors,
but only half hearted. Therefore, most languages do not support them.
Unfortunately, C++ managed extensions was an exception.

The most obvious reason why parameterless ctros are not supported is fast
array initialization. Think of this array:

array<V>^ arrayOfVTs = gcnew aray<V>(1000000);

Assume each VT instance is 8 bytes long. To initialize the array, an
instructroin similar to memset(address of array data, 800000000, 0) is used.
This is possible, because VTs can not have parameterless ctors. With a
parameterless ctor, this would be necessary to initialize the array:

for (int i = 0; i < 1000000; +i)
... call VT .ctor for i-th element ...

This would be significantly slower

Marcus

"Edward Diener" <ed*******************@tropicsoft.com> wrote in message
news:eC*************@TK2MSFTNGP03.phx.gbl...
Given

value class X
{
public:
// Not allowed: X():i(100000),s(10000) { }
// Allowed
void InitializeDefaults() { i = 100000; s = 10000; }
private:
int i;
short s;
}

How can:

1)

X x;
x.InitializeDefaults();

be better semantically than

2)

X x;

for setting the default values of 100000 for i and 10000 for s ? In other
words what is the rationale for removing the natural user-defined default
constructor for value types and forcing the user to default construct the
value type object to its zero or null values and then have to call another
function to set default values which the type may want ? I read that 2)
can not be guaranteed to occur properly but 1) evidently can ? Someone
please explain to me how a sequence of two syntax actions has a better
guarantee of properly being implemented than just one.

Apr 26 '06 #4

P: n/a
Marcus Heege wrote:
That's a strange story. .NET's base spec (the Common Langauge
Infrastructure) does support value types with parameterless constructors,
but only half hearted. Therefore, most languages do not support them.
Unfortunately, C++ managed extensions was an exception.

The most obvious reason why parameterless ctros are not supported is fast
array initialization. Think of this array:

array<V>^ arrayOfVTs = gcnew aray<V>(1000000);

Assume each VT instance is 8 bytes long. To initialize the array, an
instructroin similar to memset(address of array data, 800000000, 0) is used.
This is possible, because VTs can not have parameterless ctors. With a
parameterless ctor, this would be necessary to initialize the array:

for (int i = 0; i < 1000000; +i)
... call VT .ctor for i-th element ...

This would be significantly slower
Good, it should be slower. If the programmer wants to provide a
user-defined default constructor for a type, then filling an array
should construct each value of that type with that default constructor.
That is the normal expectation. Skewing the language/implementation is
not the way to go.

In native C++ if I create a std::vector with a size of 1000000 then each
element of my vector will be default constructed. I see no reason why
..NET should not have followed this same rule instead of choosing the bad
idea that default constructors will not be allowed for value types.

In real life of course nobody creates an array of 1 million elements.

I am piqued about this because I know that MS made a bad decision in not
allowing normal constructors/destructors for value types. But it is too
late to change anything. Once the wrong path is taken nobody will admit
to failure.

Marcus

"Edward Diener" <ed*******************@tropicsoft.com> wrote in message
news:eC*************@TK2MSFTNGP03.phx.gbl...
Given

value class X
{
public:
// Not allowed: X():i(100000),s(10000) { }
// Allowed
void InitializeDefaults() { i = 100000; s = 10000; }
private:
int i;
short s;
}

How can:

1)

X x;
x.InitializeDefaults();

be better semantically than

2)

X x;

for setting the default values of 100000 for i and 10000 for s ? In other
words what is the rationale for removing the natural user-defined default
constructor for value types and forcing the user to default construct the
value type object to its zero or null values and then have to call another
function to set default values which the type may want ? I read that 2)
can not be guaranteed to occur properly but 1) evidently can ? Someone
please explain to me how a sequence of two syntax actions has a better
guarantee of properly being implemented than just one.


Apr 26 '06 #5

P: n/a
Carl Daniel [VC++ MVP] wrote:
Edward Diener wrote:
Given

value class X
{
public:
// Not allowed: X():i(100000),s(10000) { }
// Allowed
void InitializeDefaults() { i = 100000; s = 10000; }
private:
int i;
short s;
}

How can:

1)

X x;
x.InitializeDefaults();

be better semantically than

2)

X x;

for setting the default values of 100000 for i and 10000 for s ? In
other words what is the rationale for removing the natural
user-defined default constructor for value types and forcing the user
to default construct the value type object to its zero or null values
and then have to call another function to set default values which
the type may want ? I read that 2) can not be guaranteed to occur
properly but 1) evidently can ? Someone please explain to me how a
sequence of two syntax actions has a better guarantee of properly
being implemented than just one.


It's simple: The CLR expects to be able to default-construct a value type
by 0-filling it's representation and cannot guarantee that a constructor
will be called.


I clearly did not ask how things worked but why. Your answer to my
question is "that's the way things are."

The array argument I am constantly given is flawed. A native C++
std::vector<X> of n elements default constructs each element. CLRs
attempts to get around this are just plain wrong and create a ridiculous
anomaly which tells me that I can create constructors for value types
but I can not create a default constructor for a value type. What a bad
design decision that is. OK, what's the difference. Like everybody else
I will have to kludge my way around this abortion. I just expected
better from MS.
Apr 26 '06 #6

P: n/a
Bruno van Dooren wrote:
for setting the default values of 100000 for i and 10000 for s ? In
other words what is the rationale for removing the natural user-defined
default constructor for value types and forcing the user to default
construct the value type object to its zero or null values and then have
to call another function to set default values which the type may want ?
<from http://www.codecomments.com/archive292-2006-2-806923.html>


Please, I know the rule. I clearly asked why and not how.

If you also look in "C++-CLI Standard.pdf", you read :

12.2.1 Value classes
A value class is a data structure that contains fields, function members,
and nested types. Unlike other class
types, value classes do not support user-defined destructors, finalizers,
default constructors, copy
constructors, or copy assignment operators. Value classes are designed to
allow the CLI execution engine to
efficiently copy value class objects.

Apr 26 '06 #7

P: n/a
Edward Diener wrote:
Carl Daniel [VC++ MVP] wrote:
It's simple: The CLR expects to be able to default-construct a
value type by 0-filling it's representation and cannot guarantee
that a constructor will be called.


I clearly did not ask how things worked but why. Your answer to my
question is "that's the way things are."


Oh contraire - you asked why C++/CLI prohibits defining a copy constructor -
and the reason I gave is correct: the CLR doesn't support it.

Why the CLR makes such a requirement is another question - and one that I've
never seen a satisfactory answer for. I can't help but wonder if it's
simply due to lack of planning at some very deep level in the CLR. Having
value types designed such that it's not necessary to run a default
constructor makes sense. Having them defined so it's not possible to
(always) run a default constructor seems like a design omission to me.

-cd

Apr 26 '06 #8

P: n/a
Carl Daniel [VC++ MVP] wrote:
Edward Diener wrote:
Carl Daniel [VC++ MVP] wrote:
It's simple: The CLR expects to be able to default-construct a
value type by 0-filling it's representation and cannot guarantee
that a constructor will be called. I clearly did not ask how things worked but why. Your answer to my
question is "that's the way things are."


Oh contraire - you asked why C++/CLI prohibits defining a copy constructor -


No, a default constructor.
and the reason I gave is correct: the CLR doesn't support it.

Why the CLR makes such a requirement is another question - and one that I've
never seen a satisfactory answer for. I can't help but wonder if it's
simply due to lack of planning at some very deep level in the CLR. Having
value types designed such that it's not necessary to run a default
constructor
Now you have it right.
makes sense. Having them defined so it's not possible to
(always) run a default constructor seems like a design omission to me.


I am glad someone agrees with me here. Having to write a kludge, either
a dummy constructor which takes at least one argument but actual does
default construction, or a separate function to be called to do default
construction, seems really silly to me. I know I can use a ref class
instead but I see nothing wrong with simple value classes which
initialize their variables to something other than 0 when default
constructed.
Apr 26 '06 #9

P: n/a

"Edward Diener" <ed*******************@tropicsoft.com> skrev i
meddelandet news:u8**************@TK2MSFTNGP03.phx.gbl...
Carl Daniel [VC++ MVP] wrote:

It's simple: The CLR expects to be able to default-construct a
value type by 0-filling it's representation and cannot guarantee
that a constructor will be called.


I clearly did not ask how things worked but why. Your answer to my
question is "that's the way things are."


The CLR wasn't designed for C++, but for primarilly for C#.

Now, when adopting C++/CLI to the existing infrastructure, we just
have to accept it "the way things are". C++ is still not a first class
citizen of .NET. C++/CLI is, and it turned out to be different.
Bo Persson
Apr 26 '06 #10

P: n/a
Bo Persson wrote:
"Edward Diener" <ed*******************@tropicsoft.com> skrev i
meddelandet news:u8**************@TK2MSFTNGP03.phx.gbl...
Carl Daniel [VC++ MVP] wrote:
It's simple: The CLR expects to be able to default-construct a
value type by 0-filling it's representation and cannot guarantee
that a constructor will be called.

I clearly did not ask how things worked but why. Your answer to my
question is "that's the way things are."


The CLR wasn't designed for C++, but for primarilly for C#.


C# also has constructors and a default constructor. There is no
difference between C# and C++/CLI as far as this issue goes. A design
which says that one can implement any constructor but a default
constructor is just plain bad no matter the OO language.
Apr 26 '06 #11

P: n/a
Edward Diener wrote:
The CLR wasn't designed for C++, but for primarilly for C#.

C# also has constructors and a default constructor. There is no
difference between C# and C++/CLI as far as this issue goes.


C# doesn't support default constructors for value types either. It's the
shortcoming of the CLR environment. The C++/CLI team has nothing to do
with this decision, they had to work with what they had. The CLR itself
doesn't support default and copy constructors for value types.

Theoretically Microsoft could have created C++/CLI in such a way that it
supports default constructors by generating implicit code behind this
feature. So when you instantiate a value type from C++/CLI, it could
automatically call a function, let's say "DefaultConstructor", to
initialize it for you. The problem with this is that such a value type
would not work outside of C++/CLI. If you decide to make such a type
public, and you instantiated it in C#, it wouldn't call the default
constructor automatically, and none of the other .NET languages would
do. Basically your type would fail to work as expected, unless it was
declared private to the assembly.

Yes, the compiler can do everything it wants internally. In fact, when
you create an std::vector<std::string> type and compile it with
/clr:pure, the compiler internally creates .NET value classes
std::vector and std::basic_string, which do have default constructors
(emulated!). Only those internal types can't be used from any other
module, they're private, just like the x86 code generated by a native
C++ compiler. Anything is doable in private code, but you won't be able
to make that public and use that type from other DLLs and other languages.

Microsoft decided not to allow that when you create your own value
types, even if it's a private type to the assembly.
A design which says that one can implement any constructor but a default
constructor is just plain bad no matter the OO language.


It may be true, but the CLR is not a language, it's a virtual machine.
They wanted to keep it simple and efficient. The idea behind value types
is that they are constructed by memset(&dest, 0, sizeof(dest)), and
copied using memcpy(&dest, &src, sizeof(src)). This way when you have an
array of value types, it is not needed to call the default/copy
constructor for each item individually. Value types were designed to
solve very simple problems, exactly those when you use a plain C struct
(a POD in C++).

This wouldn't be such a big problem if ref classes had either stack
syntax, or a reference counted auto-handle syntax (either way, portable
deterministic destruction at CLR-level).

But I don't see the current situation catastrophic. .NET is a reasonable
framework, much better than COM. Although in some ways .NET is a
fall-back for a true-heared C++ programmer (no const member functions,
no portable deterministic destruction, no templates), in other ways it's
a huge advancement (painless distributed component model, garbage
collection, well designed framework classes, reflection, properties,
events, two-way GUI designer). When you compare the interface that .NET
provides to the old Win32 GetProcAddress that supports only C calls,
it's "infinitely" more flexible and more object-oriented. C++/CLI does
its best to provide the best of both worlds (.NET and ISO C++), and I
think it can be further improved in a future Visual C++ release.

By the way, I don't think it's too late to introduce optional default
and copy constructors to .NET at a later time if such a decision is
made, either in C++/CLI only, or deep at CLR level. It wouldn't
automatically break existing code. Introducing const-correctness would
be much harder, now that nobody uses const at all.

Tom
Apr 27 '06 #12

P: n/a
Tamas Demjen wrote:
Edward Diener wrote:
The CLR wasn't designed for C++, but for primarilly for C#.

C# also has constructors and a default constructor. There is no
difference between C# and C++/CLI as far as this issue goes.


C# doesn't support default constructors for value types either. It's the
shortcoming of the CLR environment. The C++/CLI team has nothing to do
with this decision, they had to work with what they had. The CLR itself
doesn't support default and copy constructors for value types.


No, I don't want C++/CLI to be different than CLR in this respect. I
just want CLR value types to be fixed so that a user-defined default
constructor is allowed. The rest of your reply says nothing other than
"that's the way it is".

I think it is absurd that the CLR tells me that I can have user-defined
constructors for a value type but not a user-defined default constructor
for a value type. However it is ridiculous to argue this any further
because MS's supposed reason for instituting this limitation, the
ability to memset an array of value types to 0, is IMO absurd. It is
telling me that they know better than what I the designer of the value
type want. Thanks for being so prescient, MS !
Apr 27 '06 #13

This discussion thread is closed

Replies have been disabled for this discussion.