В чем заключаются различия между неявно объявленными и неявно определенными конструкторами копирования?
Я просматриваю страницу cppreference на конструкторах копий здесь:
http://en.cppreference.com/w/cpp/language/copy_constructor
Я прочитал 2 раздела о неявно объявленных конструкторах копий и неявно заданных конструкторах копий несколько раз, но я до сих пор не понимаю различия. Не будет ли неявно объявленный, но НЕ определенный конструктор привести к проблемам компоновщика?
Правила очень сложны. Я не помню, чтобы в С++ 03 было различие: либо у вас был созданный компилятором конструктор копий, либо нет.
Может кто-нибудь объяснить (проще говоря), какие различия/различия между этими двумя категориями?
Ответы
Ответ 1
Это поясняется в примечании в стандарте в начале раздела 12:
[Примечание: реализация будет неявно объявлять эти функции-члены для некоторых типов классов, когда программа явно не объявлять их. Реализация будет неявно определять их, если они используются odr (3.2). См. 12.1, 12.4 и 12.8. - конечная нота]
Нормативные ссылки для С++ 14 (N3936) - 12.1/5, 12.4/6, 12.8/13, 12.8/26. В каждом случае соответствующая специальная функция-член неявно определяется, если она дефолтна и не определена как удаленная, и либо odr-используется, либо явно дефолт. Если у нас есть что-то вроде
struct Foo {};
и не создаются объекты типа Foo
, все шесть специальных функций-членов (конструктор по умолчанию, деструктор, конструктор копирования, конструктор перемещения, оператор присваивания копии, оператор переадресации) неявно объявляются дефолтными, но не определенными с они не используются odr.
Ответ 2
Если существует неявно объявленный конструктор копирования, он всегда определяется 1. Варианты его определения:
- зачеркнуть
- тривиальна
- неявно определяется
Если программа пытается использовать конструктор, который определен как удаленный, то программа плохо сформирована (т.е. вы получаете ошибку компилятора). В других случаях функция вызывается.
На странице, на которой вы ссылаетесь, описывается, в каких ситуациях происходит каждая из трех указанных выше опций.
С++ 11 добавила концепцию функции delete
d, поскольку если вы хотите явно сделать класс не скопированным (и т.д.). Вы определяете его конструктор-копию как удаленный, а затем компилятор генерирует ошибку, если кто-то пытается скопировать ваш объект.
Различие между тривиально копируемым и не тривиально копируемым всегда было, но было сказано не так четко; вы вывели из правил о POD, в каких ситуациях было разрешено использовать memcpy
для копирования объектов.
1 Как указывает Брайан, более точно сказать, что он определен, если требуется. Компилятор никогда не объявляет какую-либо функцию, а затем генерирует ошибку ссылки. Но если определение функции не требуется для успешной сборки исполняемого файла, это не повлечет за собой фактическое формирование определения.