Tag Archives: default constructors error

A mistake about implicitly providing default constructors

As many C++ textbooks say, “if a class is defined and no constructor is provided, the compiler will implicitly provide a default constructor.”

the following excerpt from the original document of ISO C++ 99:

The default constructor (12.1), copy constructor and copy assignment operator (12.8), and destructor (12.4)

are special member functions. The implementation will
implicitly declare these member functions for a

class type
1. When the program does not declare explicitly them, except as noted in 12.1

will
implicitly define them
If they are used, as specified in 12.1, 12.4 and 12.8.

A default constructor for a class X is a constructor of class X that can be called without an argument. If

there is no user-declared constructor for class X, a default constructor is
implicitly declared. An implicitly-

declared default constructor is an
inline public member of its class.

An implicitly-declared default constructor for a class is
implicitly defined when
it is used to create an object

Declared -defined default constructor, everyone The set of Initializations of The

class that would be performed by a user-written default constructor for that class with
An Empty Meminitial-List (12.6.2) and an Empty Function body. If that user-written default constructor would be illformed,the program is ill-formed. Before the declared -declared default constructor for a class is implicitly

defined, all the implicitly-declared default constructors for its base classes and its nonstatic data members

shall have been implicitly defined. [Note: an implicitly-declared default constructor has an exceptionspecification(15.4).

the following excerpts from “corrigendum to sun xin vc tutorial” :

I said, “C++ also states that if a class does not provide any constructors, then C++ provides a default constructor (provided by the C++ compiler).” this statement is also incorrect, and correct:
If no constructor is defined in a class, the compiler will provide a default constructor only if:
1. If the class has virtual member functions or virtual inheritance parent class (i.e., virtual base class);
2. If the base class of the class has a constructor (either a user-defined constructor or a default constructor provided by the compiler);
3. All non-static object data members in a class that have constructors in their corresponding class (either user-defined constructors or default constructors provided by the compiler).
There are also such words in C++ Primer 14.2:

new users often mistakenly assume that if a default constructor does not exist, the compiler automatically generates a default construct

builds functions and applies them to objects to initialize the data members of the class, for the Account class we define

is not true, and the system neither generates the default constructor nor calls it. For those that contain a class data member or inheritance
The
more complex class, which is partially true, may generate a default constructor, but it will not be built-in or complex
Data members of the
combination, such as Pointers or arrays, provide an initial value.

can also be analyzed from the bottom layer:

C/C++ code

   
    
    
    class
     A
{
    public
    :
        
    int
     a;
        
    char
     
    *
    ptr;
};

    int
     main()
{
        A a;
        
    return
     
    0
    ;
}

The

code does not produce the default ctor, so the class looks like a struct under C, and none of the members need to be initialized.

evidence 1:

Assembly code

   
    
    97
    :   
    int
     main()
    98
    :   {
    0040D680
       
    push
            ebp
    0040D681
       
    mov
             ebp,esp
    0040D683
       
    sub
             esp,48h
    0040D686
       
    push
            ebx
    0040D687
       
    push
            esi
    0040D688
       
    push
            edi
    0040D689
       
    lea
             edi,[ebp-48h]
    0040D68C
       
    mov
             ecx,12h
    0040D691
       
    mov
             eax,0CCCCCCCCh
    0040D696
       
    rep
     stos    dword ptr [edi]  
    99
    :       A a
    ;
                      //Nothing to do
    
    100
    :      return 
    0
    ;
    0040D698
       
    xor
             eax,eax
    101
    :  }
    0040D69A
       
    pop
             edi
    0040D69B
       
    pop
             esi
    0040D69C
       
    pop
             ebx
    0040D69D
       
    mov
             esp,ebp
    0040D69F
       
    pop
             ebp
    0040D6A0
       
    ret
     

</ dl> however,

(1) if a member variable that requires a constructor is added, the default ctor is called, such as STD ::string

C/C++ code

   
    
    
#include 
    <
    string
    >
    
    class
     A
{
    public
    :
    
    int
     a;
    
    char
     
    *
    ptr;
    std::
    string
     test;
};

    int
     main()
{
    A a;
    
    return
     
    0
    ;
}
Assembly code

 

       
        
        
        int
         main()
        99
        :   {
        0040D680
           
        push
                ebp
        0040D681
           
        mov
                 ebp,esp
        0040D683
           
        sub
                 esp,5Ch
        0040D686
           
        push
                ebx
        0040D687
           
        push
                esi
        0040D688
           
        push
                edi
        0040D689
           
        lea
                 edi,[ebp-5Ch]
        0040D68C
           
        mov
                 ecx,17h
        0040D691
           
        mov
                 eax,0CCCCCCCCh
        0040D696
           
        rep
         stos    dword ptr [edi]
        100
        :      A a
        ;
        0040D698
           
        lea
                 ecx,[ebp-18h]
        ;
        this Pointer
        
        0040D69B
           
        call
                @ILT+
        35
        (
        A:
        :A) (
        00401028
        )
        ;
        The defaultctor is called.
        
        101
        :      return 
        0
        ;
        0040D6A0
           
        mov
                 dword ptr [ebp-1Ch],
        0
        
        0040D6A7
           
        lea
                 ecx,[ebp-18h]
        0040D6AA
           
        call
                @ILT+
        40
        (
        A:
        :~A) (
        0040102d
        )
        0040D6AF
           
        mov
                 eax,dword ptr [ebp-1Ch]
        102
        :  }
        0040D6B2
           
        pop
                 edi
        0040D6B3
           
        pop
                 esi
        0040D6B4
           
        pop
                 ebx
        0040D6B5
           
        add
                 esp,5Ch
        0040D6B8
           
        cmp
                 ebp,esp
        0040D6BA
           
        call
                __chkesp (
        00401170
        )
        0040D6BF
           
        mov
                 esp,ebp
        0040D6C1
           
        pop
                 ebp
        0040D6C2
           
        ret
         

(2) has a virtual function and will call the default ctor, such as:

C/C++ code

 [code
    =
    C
    /
    C
    ++
    ]
class A
{
public:
    int a;
    char *ptr;
    virtual void dd(){a=1;}
};

int main()
{
    A a;
    return 0;
}

 

 

corresponding Assembly

Assembly code

   
    
    
    100
    :      A a
    ;
    00401048
       
    lea
             ecx,[ebp-0Ch]
    0040104B
       
    call
            @ILT+
    15
    (
    A:
    :A) (
    00401014
    )
    ;
    The main thing here is to put the first address of the virtual function table into the first four bytes.
     

can be summarized as follows: the compiler always produces the default ctor when it is needed and when the user does not provide it. Doing so yields optimal efficiency.