c ++ - прямые и копирующие конструкторы - PullRequest
0 голосов
/ 20 мая 2018
class UnusualClass
{
    int a;
    public:
        UnusualClass(int a){std::cout<<"Direct initialization"<<std::endl;}
        UnusualClass(const UnusualClass &n){std::cout<<"Copy initialization"; }
};


int main ()
{
    UnusualClass k1(5);    //Direct initialization
    UnusualClass k2=56;   //Copy initialization
    return 0;
}

Почему компилятор выводит «Прямую инициализацию» дважды?Я провел некоторое исследование и выяснил, что, возможно, я получаю elision конструктор копирования.Можно ли получить два разных результата в этих двух случаях?Кроме того, когда я использую UnusualClass(const UnusualClass &n)=delete, я получаю сообщение об ошибке use of deleted function 'UnusualClass::UnusualClass(const UnusualClass&).Почему я получаю эту ошибку, если она все равно пропускает этот конструктор?

Я знаю, что могу получить два разных результата, используя два конструктора UnusualClass(int a); и UnusualClass(double b);, но этот трюк кажется не совсем правильным.

Ответы [ 4 ]

0 голосов
/ 20 мая 2018

Целое число 56 «неявно» связано с вашим конструктором, который ожидает целое число.Если вы хотите отключить это поведение, вы можете установить конструктор в явном виде.

explicit UnusualClass (int a) {...}

Отключение означает, что это будет обнаружено как ошибка компилятора:

UnusualClass k = 56;
0 голосов
/ 20 мая 2018
UnusualClass k1(5);    //Direct initialization
UnusualClass k2=56;   //Copy initialization

В обоих вышеупомянутых случаях вы передаете целое число, и единственный конструктор с целочисленным аргументом - это

UnusualClass(int a){std::cout<<"Direct initialization"<<std::endl;}

Следовательно, компилятор дважды выводит «Прямую инициализацию».

0 голосов
/ 20 мая 2018

Инициализация копирования не означает, что должен быть вызван конструктор копирования.

Если T является типом класса, а cv-неквалифицированная версия типа other имеет видне T или не производный от T, или если T не является типом класса, но типом другого является тип класса, определяемые пользователем последовательности преобразования, которые могут преобразовывать из типа другого в T (или в тип, производный от T, еслиT является типом класса и доступна функция преобразования), и наилучший из них выбирается с помощью разрешения перегрузки.Результат преобразования, который является prvalue temporary (until C++17) prvalue expression (since C++17), если использовался конструктор преобразования, затем используется для прямой инициализации объекта.The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

В процессе инициализации этой копии (т.е. UnusualClass k2=56;) будет выбран UnusualClass::UnusualClass(int) для преобразования int в UnusualClass, поэтому он вызывается сначала.После этого преобразованный UnusualClass используется для прямой инициализации объекта k2, поэтому концептуально требуется конструктор копирования.До того, как в C ++ 17 случится даже copy elision , конструктор копирования должен быть доступен, поэтому, когда вы делаете его delete, вы не смогли скомпилировать.Начиная с C ++ 17 копия elision гарантируется, и конструктор копирования больше не должен быть доступен.

0 голосов
/ 20 мая 2018

Это не copy initialization:

UnusualClass k2=56;   // NOT Copy initialization
                      // for 56 is not of type UnusualClass

Это вызовет конструктор:

UnusualClass(int a)

Я думаю, вы имели в виду:

UnusualClass k1(5);    //Direct initialization
UnusualClass k2{k1};   //Copy initialization
UnusualClass k2 = k1;  //Copy initialization

Примечаниетип, необходимый в copy initialization.

UnusualClass(const UnusualClass &n) // const reference to type UnusualClass

. Тип объекта должен быть UnusualClass, а не int

ОБНОВЛЕНИЕ

Я получаю сообщение о том, что использование удаленной функции

UnusualClass::UnusualClass(const UnusualClass&).

Почему я получаю эту ошибку, если она все равно пропускает этот конструктор?

UnusualClass::UnusualClass(const UnusualClass&) = delete;

означает:

From cppreference

Предотвращение неявной генерации конструктора копирования.

Таким образом, вам необходимо определить свою собственную копиюКонструктор.

ОБНОВЛЕНИЕ 2

Подробнее см. ответ @ songyuanyao на copy-initialization

...