views:

237

answers:

2

I'm working with some C++/CLI code (new syntax) and am trying to declare a generic type and want to set a member variable to it's default.

In C#:

class Class<T>
{ 
    T member = default(T);
}

What's the equivalent in CLI?

generic<typename T> public ref class Class 
{
public:
    Class() : member(default(T))  // <-- no worky
    {
    }    
private:
        T member;
};
A: 

But isn't the private member already initialized with the default constructor?

Assaf Lavie
Is it? It's my recollection that C++ does not initialize member variables. How C++ with a runtime and a managed heap initializes memory I have no idea.
dkackman
In C++ member variables are initialized with their default constructor. You might be thinking that ints don't get initialized to zero, or something.. that's true of course. But types that have constructors get their default constructors called.
Assaf Lavie
Fair point, but given that my type parameter could be a value type or a reference type it leaves me with no way to initialize it. The vary reason default(T) is part of C#. I gues I was just expecting a CLI equivalent.
dkackman
You can think of it this way: ALL types in C++ have a constructor, be it user-defined or compiler-supplied. For intrinsic types, the 'constructor' leaves it at whatever bitstream is on the space on the stack/heap where the variable occupies. So it really just depends on what the constructor does.
blwy10
And for this very reason I've always been in the habit of populating the member initialization list with explicit values.
dkackman
The CLR zero initializes all value types so you don't need to do anything special. 'int x;' will always be 0. FxCop has a rule complaining about explicit zero initialization of fields because it will cause the emitted ctor machine code to be larger and (marginally) slower, both in runtime and JIT time.
Nathan Howell
+2  A: 

Interestingly enough the syntax makes it looks like this: T(). It does require the addition of a copy constructor.

generic<typename T> 
    public ref class Class 
{
public:
    Class() : member(T())  
    {
    } 

    Class(Class^ c)
    {
     member = c->member;
    }

private:
    T member;
};

Edit DOH This works too (been in C# land for so long I forgot that NULL and 0 are the same thing in C++, hence no need for different value and reference type default values):

generic<typename T> 
    public ref class Class 
{
public:
    Class() : member(0)  
    {
    } 

    Class(Class^ c)
    {
     member = c->member;
    }

private:
    T member;
};
dkackman
You're right about T() and about 0 being a valid null pointer constant, but `member(0)` isn't always right: it requires T has a ctor that takes an int.
Roger Pate
Class<Object^> c = gcnew Class<Object^>(); compiles just fine. Does the templated type require that constructor (as Object does not have one) or is it in this case that the the managed handle pointer type requires that constructor?
dkackman
'nullptr' is C++/CLI's equivalent of C# 'null'. '0' or 'NULL' is not a managed pointer type.
Nathan Howell