Question

C++11 adds the ability for telling the compiler to create a default implementation of any of the special member functions. While I can see the value of deleting a function, where's the value of explicitly defaulting a function? Just leave it blank and the compiler will do it anyway.

The only point I can see is that a default constructor is only created when no other constructor exists:

class eg {
public:
    eg(int i);
    eg() = default; 
};

But is that really better than how you do it now?

class eg {
public:
    eg(int i);
    eg() {}
};

Or am I missing a use-case?

Was it helpful?

Solution

A defaulted constructor will have a declaration, and that declaration will be subject to the normal access rules. E.g. you can make the default copy constructor protected. Without these new declarations, the default generated members are public.

OTHER TIPS

Those examples from Stroustrup's website might help you understand the point:

defaulted and deleted functions -- control of defaults

The common idiom of "prohibiting copying" can now be expressed directly:

class X {
  // ...

  X& operator=(const X&) = delete;    // Disallow copying
  X(const X&) = delete;
};

Conversely, we can also say explicitly that we want to default copy behavior:

class Y {
  // ...
  Y& operator=(const Y&) = default;   // default copy semantics
  Y(const Y&) = default;

};

Being explicit about the default is obviously redundant, but comments to that effect and (worse) a user explicitly defining copy operations meant to give the default behavior are not uncommon. Leaving it to the compiler to implement the default behavior is simpler, less error-prone, and often leads to better object code. The "default" mechanism can be used for any function that has a default. The "delete" mechanism can be used for any function. For example, we can eliminate an undesired conversion like this:

struct Z {
  // ...

  Z(long long);     // can initialize with an long long
  Z(long) = delete; // but not anything less
};

As well as changing the accessibility (private/protected) of generated functions, you will be able to make them virtual.

struct S
{
    virtual ~S();
    virtual S& operator=(const S&);
};

S::~S() = default;
S& S::operator=(const S&) = default;

The following aspects of defaulted functions can be modified:

  • access (be made non-public)
  • virtual
  • explicit (constructors)
  • exception specifications
  • const-ness of parameters

but to do so, the functions must be defined outside the class (8.4.2/2 in the C++0x Final Committee Draft).

A version of the original proposal by Lawrence Crowl is here.

Thanks to Roger Pate for the clarification and citation.

1) Implicitly generated destructors are currently not virtual. So you need to define them in order to make them virtual, in which case they are not as efficient. With =default, You will have both virtual and efficent as implicitly generated destructors.

2) They will have access specifiers, contrary to implicitly generated ones.

3) If you inline your defaulted constructor, your class still remain trivial.

Here is an article elaborating this new feature.

I suspect that being able to default generate the copy constructor will be actually useful. I can't see a use for default generating the default constructor since as you say the implementation you type in would be shorter.

See Item 17 from Scott Meyer's great book "Effective Modern C++". It describes many conditions under which default copy constructors, copy operations, and move operations are generated (or NOT generated).

In other words, the compiler might not "do it anyway". But if the default special member function makes sense, the user could use the "default" keyword to explicitly tell the compiler to generate a default function that otherwise not be generated.

From the Things to Remember at the end of Item 17:

  • Move operations are generated only for classes lacking explicitly declared move operations, copy operations, or a destructor.

  • The copy constructor is generated only for classes lacking an explicitly declared copy constructor, and it’s deleted if a move operation is declared. The copy assignment operator is generated only for classes lacking an explicitly declared copy assignment operator, and it’s deleted if a move operation is declared. Generation of the copy operations in classes with an explicitly declared destructor is deprecated.

For me its the disabling feature that will be useful, For most of the classes I currently create I disable copying & assignment - it will be nice to have a feature the compiler can recognise to do this, rather than depending on linker errors.

Defaulting is more useful for copy-constructors if you have a class with lots of attributes. For example, if you have this class:

class MyClass {
private:
   int offset;
   std::string name;
   std::vector<Person*> relatives;
   float weight;
   MyClass* spouse;
   Vehicle* car;
   double houseArea;
   Date birth;
   Person* parents[2];

public:
   /* Default constructor will be defined here */
};

instead of defining the copy-constructor this way:

MyClass(const MyClass& that) :
   offset(that.offset),
   name(that.name),
   relatives(that.relatives),
   weight(that.weight),
   spouse(that.spouse),
   car(that.car),
   houseArea(that.houseArea),
   birth(that.birth),
   parents(that.parents)
{}

you would define this way:

MyClass(const MyClass&) = default;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top