If a destructor is deleted, will the compiler still implicitly generate a default constructor?

172 Views Asked by At

If a destructor is deleted, will the compiler still implicitly generate a default constructor?

The following code can be compiled by GCC:

struct A
{
    ~A() = delete;
    int x;
    int y;
    virtual void foo()
    {
    }
};

int main()
{
    A *pmc = new A; // Allowed by the compiler GCC, but causes memory leak
    return 0;
}

This suggests that GCC believes it can implicitly generate a default constructor in this situation. The assembly code for the default constructor can also be viewed on Godbolt:

A::A() [base object constructor]:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     edx, OFFSET FLAT:vtable for A+16
        mov     rax, QWORD PTR [rbp-8]
        mov     QWORD PTR [rax], rdx
        nop
        pop     rbp
        ret

However, when checking with type traits, the answer is negative:

cout << is_default_constructible<A>::value; // false

So, does is_default_constructible represent the attitude of the C++ standard? That is to say, at the language standard level, the generation of a default constructor is not allowed, but at the compiler implementation level, the generation of a default constructor is allowed.

Is this correct?

1

There are 1 best solutions below

8
user17732522 On

Yes (to the question in the title), a default constructor is always implicitly declared if no other constructor is user-declared, although it may be defined as deleted if subobjects can't be default-initialized or destructed. Nothing about the destructor of the class itself is relevant:

If there is no user-declared constructor for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted ([dcl.fct.def]).

- [class.default.ctor] p1

std::is_default_constructible<A> fails because the std::is_(*_)constructible traits do not only check whether the object can be constructed. They instead check whether a definition of a variable with the corresponding types in direct-initialization would be well-formed, i.e. here whether

A a();

would be well-formed, except that the declaration is not interpreted as a function declaration. Such a variable definition is only well-formed if the destructor is also usable.


That is to say, at the language standard level, the generation of a default constructor is not allowed, but at the compiler implementation level, the generation of a default constructor is allowed. Is this correct?

No, this question doesn't make any sense to begin with. If the standard specifies that a constructor is not implicitly declared/defined, then a compiler conforming to the standard can't possibly do it another way.