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

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 in the face of a default constructor 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, since both are essentially doing the exact same thing and 1) is obviously more verbose than 2)..



Answer this question

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

  • Alkiris

    I can't speak to the philosophy like others have already, but I have a possible solution for your immediate problem. Call the initialize function from your constructor. It seems a bit like a waste of time to have to create an Initialize function that you might not ever use outside of the constructor, but it will get the job done:


    value class X
    {
    public:
    X() { InializeDefaults(); }
    void InitializeDefaults() { i = 100000; s = 10000; }

    private:
    int i;
    short s;
    }


  • KerryDBerry

    Hi,
    I never heard that one was better than the other or even that one could not occur correctly (this would be very bad if it happened).

    One reason for moving the initializations from the constructor to an init function would be if during the life time of your object you'd need to reset it to its initial values, in that case it makes sense that you have an init function so you can call it to initialize your object again.


  • xiaopang

    The canonical example is an array of value types - the CLR will not call the default constructor to initialize each element of the array.

    So Instead of leaving the C++ user in a position where the default constructor might be called in some cases and not in others - not to mention the possibility that what these cases are may change from one release of the CLR to another - the Visual C++ team decided to come down on the side of consistancy and disallow default constructors on value-types.

    Note: value-types are zero initialized so every value-type needs to be able to accept the zeroed-state as a valid instance.



  • dalmond

    If you are going to allow constructors for value types, then those constructors should always be in effect like C++ classes. If you want to treat value types strictly like C structs, then you should have done that. What you have done is created an in-between animal, neither fish nor fowl, and have therefore failed in your design goals IMO. It is laughable that to construct a value type with certain starting values one has to default construct the object and then call some function to set those starting values. Think about it rather than defend the status quo. Anybody can do the latter.

    Anyway what's the point. To construct value types with a user-defined set of starting values I will have to call some kludgy function after default construction to do it. Horrendous but since it doesn't bother MS why should it bother me..

  • Kary

    Come to think of it, since an "int" is a value type, MS should have taken away the ability to initialize an "int" upon construction by writing "int i(5);" or "int i = 5" in CLR. After all an array of ints can never be default constructed to anything but 0 for each one. Therefore by MS's logic one should have had to write "int i;" followed by "i = 5;" instead for CLR construction of an "int" to a non-zero value. But of course that is laughable. Too bad you do not see the equivalent two-step default initialization of a value class as equally laughable.

  • Perro

    No, you do not understand. For value classes the CLR always creates a default constructor which initializes all the members to their equivalent 0 values. The designer of the value class is not allowed to implement a default constructor at all, but may implement as many non-default constructors as he likes. So in order to default construct a value class object to something other than 0 s, the designer must either create a dummy constructor which takes at least one argument, which then ignores its argument and sets those values, or the designer must create a separate public function to set its values, and the programmer which wants to default construct the values to those set values must use the CLR generated default constructor and then call that separate public function.

    In other words, the ability to default construct a value class object to something other than 0 s must be a total kludge. This despite the fact that all the OO languages of which I know support user-defined default constructors for all "classes".

  • MikeCad

    The CLR not calling a user-defined default constructor to initialize each element of an array appears totally wrong to me. What is the reason for that So because of that one has to kludge a special function to default construct value types, even though that is what constructors in OO languages are all about I think someone in the CLR design time should have thought about this a little longer and come up with the right solution. I know each system deals with compromises, but limiting a natural OOP idiom which nearly every OO language has, the ability to have different constructors and use them when instantiating an object, is not the way to design CLR.

  • ch_cu

    Performance.

    Value-types are not and were not designed to be OO types - they are sealed so you cannot inherit from them, virtual functions (if they have any) are called non-virtually. Value-types are design for performance - they should be used to represent discrete types (like a point). If you want full OO types then you should use a reference-type.



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