Каковы все функции-члены, созданные компилятором для класса? Это происходит постоянно?

Каковы все функции-члены, созданные компилятором для класса? Это происходит постоянно? как деструктор. Моя забота заключается в том, создан ли он для всех классов и зачем нужен конструктор по умолчанию?

Ответ 1

С++ 98/03

Если они нужны,

  1. компилятор сгенерирует для вас конструктор по умолчанию, если вы не объявите свой собственный конструктор.
  2. компилятор сгенерирует для вас конструктор копии, если вы не объявите свой собственный.
  3. компилятор сгенерирует для вас копию оператора присваивания, если вы не объявите свой собственный.
  4. компилятор сгенерирует для вас деструктор, если вы не объявите свой собственный.

Как сказал Петер в полезном комментарии, все они генерируются компилятором только тогда, когда они необходимы. (Разница в том, что когда компилятор не может их создать, это нормально, если они не используются.)


С++ 11

С++ 11 добавляет следующие правила, которые также действительны для С++ 14 (кредиты для towi, см. этот комментарий):

  • Компилятор создает конструктор move constructor, если
    • не существует объявленного пользователем экземпляра конструктора и
    • не существует объявленного пользователем оператора копирования assignment operator и
    • не существует объявленного пользователем оператора перемещения assignment operator и
    • не существует объявленного пользователем деструктора,
    • не помечено delete d,
    • и все участники и базы являются подвижными.
  • Аналогично для move оператора присваивания, оно генерируется, если
    • не существует объявленного пользователем экземпляра конструктора и
    • не существует объявленного пользователем оператора копирования assignment operator и
    • нет объявленного пользователем конструктора move constructor и
    • не существует объявленного пользователем деструктора,
    • не помечено delete d,
    • и все участники и базы являются подвижными.

Обратите внимание, что эти правила немного сложнее правил С++ 03 и имеют больше смысла на практике.

Для более простого понимания того, что есть в приведенном выше:

class Thing {
public:
    Thing();                        // default constructor
    Thing(const Thing&);            // copy c'tor
    Thing& operator=(const Thing&); // copy-assign
    ~Thing();                       // d'tor
    // C++11:
    Thing(Thing&&);                 // move c'tor
    Thing& operator=(Thing&&);      // move-assign
};

Дополнительная информация: если вы новичок в С++, подумайте о дизайне, который не требует от вас реализации какого-либо из пяти, известных как , "Правило нуля" из статьи, написанной Мартиньо Фернандес.

Ответ 2

Вы имеете в виду 'defined' by 'created'?

$12.1 - "Конструктор по умолчанию (12.1), конструктор копирования и оператор назначения копирования (12.8) и деструктор (12.4) являются специальными функциями-членами.

Если "created" означает "defined", тогда вот важные части из С++ Standard.

- Неявно объявленный конструктор по умолчанию для класса неявно определяется, когда он используется для создания объекта его типа класса (1.8).

-Если класс не имеет объявленного пользователем деструктора, деструктор объявляется неявно. Неявно объявленный деструктор неявно определяется, когда он используется для уничтожения объекта его типа класса.

-Если определение класса явно не объявляет конструктор копирования, он объявляется неявно. Неявно объявленный конструктор копирования неявно определяется, если он используется для инициализации объекта его типа класса из копии объекта его типа класса или типа класса, полученного из его типа класса).

-Если определение класса явно не объявляет оператор присваивания копии, он объявляется неявно. Оператор назначения неявно объявленных копий неявно определяется, когда объекту его типа класса присваивается значение его типа класса или значение типа класса, полученного из его типа класса.

Ответ 3

По умолчанию, если он не реализован пользователем, компилятор добавляет некоторые функции-члены в класс. Они называются большой четверкой:

  • конструктор по умолчанию
  • конструктор копирования Оператор копирования
  • (присвоение)
  • деструктор

В зависимости от типов членов и какой из перечисленных функций вы предоставляете себя, все они не будут созданы.

Ответ 4

С++ 17 N4659 стандартный черновик

https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf  6.1 "Объявления и определения" содержит примечание, которое, вероятно, суммирует их все:

3 [Примечание: В некоторых случаях реализации С++ неявно определяют конструктор по умолчанию (15.1), копировать конструктор (15.8), конструктор перемещения (15.8), оператор назначения копирования (15.8), оператор назначения перемещения (15.8), или деструктор (15.4) функций-членов. - примечание конца] [Пример: дано

#include <string>

struct C {
  std::string s;         // std::string is the standard library class (Clause 24)
};

int main() {
  C a;
  C b = a;
  b = a;
}

реализация будет неявно определять функции, чтобы сделать определение C эквивалентным

struct C {
  std::string s;
  C() : s() { }
  C(const C& x): s(x.s) { }
  C(C&& x): s(static_cast<std::string&&>(x.s)) { }
  // : s(std::move(x.s)) { }
  C& operator=(const C& x) { s = x.s; return *this; }
  C& operator=(C&& x) { s = static_cast<std::string&&>(x.s); return *this; }
  // { s = std::move(x.s); return *this; }
  ~ C() { }
};

— end example ]

Условия, при которых они объявляются, описаны по адресу: Условия для автоматической генерации ctor по умолчанию /copy/move и оператора присваивания copy/move?

Отличный способ убедиться, что у чего-то есть значение по умолчанию, состоит в том, чтобы попытаться использовать его = default, как объяснено в: Что такое " default " значит после урока & # 39; объявление функции?

В приведенном ниже примере это выполняется, а также выполняются все неявно определенные функции.

#include <cassert>
#include <string>

struct Default {
    int i;
    Default()                          = default;
    Default(const Default&)            = default;
    Default& operator=(Default&)       = default;
    Default& operator=(const Default&) = default;
    Default(Default&&)                 = default;
    Default& operator=(Default&&)      = default;
    ~Default()                         = default;
};

struct Instrument {
    int i;
    static std::string last_call;
    Instrument()                             { last_call = "ctor"; }
    Instrument(const Instrument&)            { last_call = "copy ctor"; }
    Instrument& operator=(Instrument&)       { last_call = "copy assign"; return *this; }
    Instrument& operator=(const Instrument&) { last_call = "copy assign const"; return *this; }
    Instrument(Instrument&&)                 { last_call = "move ctor";  }
    Instrument& operator=(Instrument&&)      { last_call = "move assign"; return *this; }
    ~Instrument()                            { last_call = "dtor"; }
};
std::string Instrument::last_call;

int main() {
    // See what the default constructors are doing.
    {
        // Default constructor.
        Default ctor;
        // i is uninitialized.
        // std::cout << ctor.i << std::endl;
        ctor.i = 1;

        // Copy constructor.
        Default copy_ctor(ctor);
        assert(copy_ctor.i = 1);

        // Copy assignment.
        Default copy_assign;
        copy_assign = ctor;
        assert(copy_assign.i = 1);

        // Copy assignment const.
        const Default const_ctor(ctor);
        Default copy_assign_const;
        copy_assign_const = const_ctor;
        assert(copy_assign_const.i == 1);

        // Move constructor.
        Default move_ctor(std::move(ctor));
        assert(move_ctor.i == 1);

        // Move assignment.
        Default move_assign;
        move_assign = std::move(ctor);
        assert(move_assign.i == 1);
    }

    // Check that the constructors are called by these calls.
    {
        // Default constructor.
        Instrument ctor;
        assert(Instrument::last_call == "ctor");

        // Copy constructor.
        Instrument copy_ctor(ctor);
        assert(Instrument::last_call == "copy ctor");

        // Copy assignment.
        copy_ctor = ctor;
        assert(Instrument::last_call == "copy assign");

        // Copy assignment const.
        const Instrument const_ctor(ctor);
        Instrument copy_assign_const;
        copy_assign_const = const_ctor;
        assert(Instrument::last_call == "copy assign const");

        // Move constructor.
        Instrument move_ctor(std::move(ctor));
        assert(Instrument::last_call == "move ctor");

        // Move assignment.
        Instrument move_assign;
        move_assign = std::move(ctor);
        assert(Instrument::last_call == "move assign");

        // Destructor.
        {
            Instrument dtor;
        }
        assert(Instrument::last_call == "dtor");
    }
}

GitHub upstream.

Протестировано с GCC 7.3.0:

g++ -std=c++11 implicitly_defined.cpp

Ответ 5

Другие ответы говорят вам, что создано, и что компилятор может генерировать их только при использовании.

Моя забота заключается в том, создан ли он для всех классов...

Зачем? Думаете ли вы создать нежелательный код в исполняемом файле? Вряд ли, но вы можете достаточно легко проверить свою среду.

Или, может быть, ваша забота заключалась в том, что он может не создавать конструктор, если вы этого хотите? Не о чем беспокоиться... они всегда создаются при необходимости и не предоставляются пользователем.

... и зачем нужен конструктор по умолчанию?

Поскольку классы могут иметь внутри себя объекты со своими собственными деструкторами, которые необходимо систематически вызывать. Например, учитывая...

struct X
{
    std::string a;
    std::string b;
};

... деструктор по умолчанию гарантирует, что деструкторы для a и b будут выполняться.