Skip to content

Latest commit

 

History

History
171 lines (121 loc) · 5.04 KB

default_constructors_=default_0_delete.md

File metadata and controls

171 lines (121 loc) · 5.04 KB

Default Constructors

A default constructor is a constructor that

  1. Has no parameters:

  2. If it has parameters, all the parameters have default values.

class Foo {
public:
  Foo();                           // user-defined default constructor with no arguments
  Foo(int n= 0);                   // user-define default constructor with one default argument
  Foo(int a, int b, int v= 0);     // Constructor
};

A default constructor is a constructor which can be called with no arguments. If no user-defined constructor exists for a class Foo and one is needed, the compiler implicitly declares a default parameterless constructor Foo::Foo(). This constructor is an inline public member of its class. The compiler will implicitly define Foo::Foo() when the compiler uses this constructor to create an object of type Foo. The constructor will have no constructor initializer and a null body. No default constructor is created for a class that has any constant or reference type members.

struct A
{
    int x;
    A(int x = 1): x(x) {} // user-defined default constructor
};
 
struct B: A
{
    // B::B() is implicitly-defined, calls A::A()
};
 
struct C
{
    A a;
    // C::C() is implicitly-defined, calls A::A()
};
 
struct D: A
{
    D(int y): A(y) {}
    // D::D() is not declared because another constructor exists
};
 
struct E: A
{
    E(int y): A(y) {}
    E() = default; // explicitly defaulted, calls A::A()
};
 
struct F
{
    int& ref; // reference member
    const int c; // const member
    // F::F() is implicitly defined as deleted
};
 
// user declared copy constructor (either user-provided, deleted or defaulted)
// prevents the implicit generation of a default constructor
 
struct G
{
    G(const G&) {}
    // G::G() is implicitly defined as deleted
};
 
struct H
{
    H(const H&) = delete;
    // H::H() is implicitly defined as deleted
};
 
struct I
{
    I(const I&) = default;
    // I::I() is implicitly defined as deleted
};
 
int main()
{
    A a;
    B b;
    C c;
//  D d; // compile error
    E e;
//  F f; // compile error
//  G g; // compile error
//  H h; // compile error
//  I i; // compile error
}

Refs: 1, 2

code

Explicitly Defaulted and Deleted Special Member Functions

C++ compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor if it does not declared. These functions are known as the special member functions. That's enable you to create, copy, and destroy objects without any additional code. C++11 introduced move semantics to the language and added the move constructor and move-assignment operator to the list of special member functions that the compiler can automatically generate.

You can make any of class member functions to use the default implementation (automatic generation).

Because of the performance benefits of trivial special member functions, we recommend that you prefer automatically generated special member functions over empty function bodies when you want the default behavior.

Refs: 1

=default

In Foo, For the type to qualify as trivial the presence of the Foo(int a, int b) constructor requires that you provide a default constructor., you must explicitly default that constructor.

struct noncopyable
{
  noncopyable() =default;
  noncopyable(const noncopyable&) =delete;
  noncopyable& operator=(const noncopyable&) =delete;
};

=delete

Deleted functions enable you to prevent problematic type promotions from occurring.

= default vs empty user defined function {}

When a class or struct in C++ has compiler-provided or explicitly defaulted special member functions, then it is a trivial type. It occupies a contiguous memory area. In Foo, the presence of the Foo(int a, int b) constructor requires that you provide a default constructor. For the type to qualify as trivial, you must explicitly default that constructor. Please note that the member variables have different access control (public and private mixed)

struct Foo
{
   int i;
   Foo(int a, int b) : i(a), j(b) {}
   Foo() = default;
private:
   int j;   
};  

It could be verified:

    std::cout << "Foo is trivial is " << std::is_trivial<Foo>() << std::endl;

changing

   Foo() = default;

to this

   Foo(){};

will make it non-trivial constructor.

Refs: 1, 2, 3