stonebird
stonebird

Reputation: 339

c++ template constructor initialization

template<class T>
class Node
{
    public:
    Node(Node<T>* next=NULL, T data=T()) : _next(next), _data(data)
    {
    } 
    Node<T>* _next;
    T _data;
};

I'm new to c++ template. For default parameters, is T data = T() the standard way to do it? Maybe T data = 0 is ok too?

Upvotes: 5

Views: 4383

Answers (2)

ildjarn
ildjarn

Reputation: 62995

This really has nothing to do with constructors; what you're seeing is a combination of default function arguments and value-initialization.

The latter is described in the C++03 standard, §8.5/5:

To value-initialize an object of type T means:

  • if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized

and

To zero-initialize an object of type T means:

  • if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
  • if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized;
  • if T is a union type, the object’s first named data member89) is zero-initialized;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.

And lastly, piecing it together, §8.5/7:

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

Upvotes: 3

Ben Voigt
Ben Voigt

Reputation: 283893

That's not "constructor initialization", that's a default parameter. It allows the caller to provide fewer arguments than the function has, the unspecified arguments will take on the default value.

Another way to do it would be:

template<class T>
class Node
{
    public:
    Node(Node<T>* next, T data) : m_next(next), m_data(data) {} 
    Node(Node<T>* next) : m_next(next), m_data() {} 
    Node(void) : m_next(NULL), m_data() {} 

    Node<T>* m_next;
    T m_data;
};

Where using fewer than two arguments is also allowed, but calls different constructors (that have almost the same behavior).

There are a number of advantages to using separate overloads:

  • Doesn't require a copy-constructor, if the data parameter is always omitted.
  • Doesn't require a default constructor, if the data parameter is always provided.

Upvotes: 7

Related Questions