Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between constructor "=default" and the compiler generated constructor in C++?

Example for code:

class Dog
{
private:
    int x;
public:
    Dog()=default;
};

Vs. this code:

class Dog
{
private:
    int x;
};

What is the difference between the constructor that is "=default" (the first code) and the constructor that the compiler creates (like the second code)?

like image 706
Noya_G Avatar asked Aug 17 '21 17:08

Noya_G


People also ask

What is the difference between default constructor and constructor?

A Default constructor is defined to have no arguments at all as opposed to a constructor in general which can have as many arguments as you wish.

What is the difference between default constructor and constructor with default arguments?

A default constructor is a 0 argument constructor which contains a no-argument call to the super class constructor. To assign default values to the newly created objects is the main responsibility of default constructor.

What is compiler generated constructor?

The compiler generates a default constructor, a constructor that takes no arguments, only when you have not declared any other constructor. If you have declared only a constructor that takes parameters, code that attempts to call a default constructor causes the compiler to produce an error message.

Why a compiler given constructor is called as default constructor?

It is a special type of method which is used to initialize the object. Every time an object is created using the new() keyword, at least one constructor is called. It calls a default constructor if there is no constructor available in the class. In such case, Java compiler provides a default constructor by default.

When does the compiler add a default constructor to the code?

The compiler adds a default constructor to the code only when the programmer writes no constructor in the code. If the programmer writes any constructor in the code, then the compiler doesn't add any constructor. Every default constructor is a 0 argument constructor but every 0 argument constructor is not a default constructor.

What is a constructor in C++?

The name of constructor is same as class name. Constructor should not have any return type. The constructor which does not have any parameter. If there is no constructor in a class, Compiler automatically creates a default constructor. Constructor are basically used to initialize and objects. It is a block of codes similar to a method.

Is it possible to create default constructor in Java?

Answer to your question is No. Java won't provide a default constructor if you write any kind of constructor in class. One difference between them is that the body of default constructor will always be empty whereas we can insert our own code in no-arg constructor. Show activity on this post.

What is the difference between default constructor and non-arg constructor?

This default constructor calls its parent class’s non-parameterised constructor It initializes class variables to their default values. While non-arg constructor is defined by a programmer only. It can also intializes the variables.


3 Answers

Dog() = default; is a user declared constructor (not to be confused with a user defined constructor). It is a defaulted default constructor. Typically you would use it when the class has other constructors but you still want the compiler to generate a default constructor (or rather a "defaulted default constructor". This is C++ terminology at its best. Note how the two "default"s have slightly different meaning).

A user declared constructor prevents a class from being an aggregate. From cppreference, only for C++20:

An aggregate is one of the following types:

  • array type
  • class type (typically, struct or union), that has
    • no private or protected direct non-static data members
    • no user-declared or inherited constructors
    • no virtual, private, or protected base classes
    • no virtual member functions

As an example, consider:

#include <iostream>
#include <type_traits>

class Dog {
    int x;
public:
    Dog()=default;
};

class Horse {
    int x;
};

class Swan {
public: 
    int x;
};

class Cow {
public:
    int x;
    Cow() = default;
};

int main() {
    std::cout << std::is_aggregate_v<Dog>;
    std::cout << std::is_aggregate_v<Horse>;
    std::cout << std::is_aggregate_v<Swan>;
    std::cout << std::is_aggregate_v<Cow>;
}

Output

0010

The first two, Dog and Horse, resemble your two versions of Dog. They are not aggregates, because they have private members. Swan is an aggregate, but Cow is not, because it has a user declared constructor.

Something that works with aggregates, but not with non-aggregates, is designated initializers (same cppreference page):

Swan s{.x=3};    // OK
Cow c{.x=4};     // Error: Cow is not an aggregate

TL;DR: I am not aware of a difference between your two Dogs, but in general the presence of a user declared constructor can make a difference.

like image 83
463035818_is_not_a_number Avatar answered Oct 10 '22 06:10

463035818_is_not_a_number


I'll limit the scope to a default constructor, as in the question's code and tag. For the most part, you'll get the same effect since = default; loosely means "give me the compiler-generated one". It's important to note what exactly having no declaration does:

If there is no user-declared constructor for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted. An implicitly-declared default constructor is an inline public member of its class.

If your declaration changes any of these, it will no longer be the exact same as the implicit one. In the standard, Dog() = default; is a user-declared constructor, but not a user-provided constructor. There are a couple small differences between having a user-declared default constructor and having no constructor.

As mentioned, aggregates were fixed:

struct not_agg {
    not_agg() = delete;
    int x;
};

Before the fix, such a class could be created via aggregate initialization: not_agg{}. Naturally, this also extends to = default;. Per [dcl.init.aggr]:

An aggregate is an array or a class with

  • no user-declared or inherited constructors

There is also rationale given for this change in annex C:

Remove potentially error-prone aggregate initialization which may apply notwithstanding the declared constructors of a class.


An interesting, but very tiny difference is that a class with a user-declared constructor is not allowed to have non-static data members of the same name as the class:

class c {
    int c; // Okay
};

class c2 {
    c2() = default;
    int c2; // Error
};

This is due to [class.mem]/21:

In addition, if class T has a user-declared constructor, every non-static data member of class T shall have a name different from T.

like image 27
chris Avatar answered Oct 10 '22 05:10

chris


  1. Default declared constructors can be guarded with protected or private access. Not declared default constructors are always inline public members of their classes.
  2. = default constructors are instantiated like usual member functions, may be inline or not, they have strong linkage references in the second case. The compiler creates not declared default constructors as inline member functions with weak linkage references.
  3. As mentioned in the comments, =default constructors are user-defined constructors and their classes are not aggregate types.
like image 3
273K Avatar answered Oct 10 '22 04:10

273K