Конструкторы сгенерированные компилятором

Это просто быстрый вопрос, чтобы правильно понять, что происходит, когда вы создаете класс с таким конструктором:

class A
{
  public:
    A() {}
};

Я знаю, что конструктор по умолчанию не создается, поскольку он уже определен, но являются конструкторами копирования и присваивания, сгенерированными компилятором, или, другими словами, мне нужно объявить частный конструктор копирования и частный оператор присваивания, чтобы предотвратить это?

class A
{
  private:
    // needed to prevent automatic generation?
    A( const A& );
    A& operator=( const A& );
  public:
    A() {}
};

Ответ 1

Да. Конструктор копирования, оператор присваивания и деструктор всегда создаются независимо от других конструкторов и операторов.

Если вы хотите отключить его, то, что у вас там, идеально. Это тоже довольно распространено.

Ответ 2

Да, операторы копирования и назначения копирования все еще созданы, даже если вы объявляете свой собственный конструктор по умолчанию.

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

Обратите внимание, что возможно иметь как собственный конструктор копирования, так и один компилятор:

struct A {
  A() { }
  A(A const&, int foo); 
}; // compiler declares a copy constructor now

// make the second parameter have a default argument
// now this constructor is a copy constructor too. 
inline A::A(A const&, int foo = 0) {

}

int main() {
  A a;
  A b = a; // ambiguity between compiler one and our custom one!
}

Однако стандарт позволяет компиляторам принимать этот код, но эффект похож на поведение undefined: программа плохо сформирована, но для этой программы не требуется никаких предупреждений/ошибок. (ранние версии GCC не отклоняют этот код, последние отвергают его).

Ответ 3

Если вы хотите отключить копирование и назначение, тогда лучше унаследовать класс, который имеет частный конструктор копирования и оператор присваивания (boost::noncopyable является готовым).

1) Меньше повторного набора текста.

2) Самодокументирование (надеюсь).

3) Более сильная проверка того, что эти операции не могут быть вызваны (сам класс и друзья могут делать копии), что приведет к компилятору, а не к ошибке компоновщика).

4) Не скроет конструктор по умолчанию:)

#include <boost/noncopyable.hpp>

class X : boost::noncopyable
{
};

int main()
{
    X a, b;     //has default constructor
    //X c(a);   //but can't be copied
    //a = b;    //or assigned
}