Инициализировать элемент объекта со ссылкой в ​​списке инициализации - PullRequest
1 голос
/ 13 января 2012

Я правильно делаю?Это очень упрощенная версия моего кода:

class Logger {
   public:
      Logger(std::ostream) { /*...*/}
};

class Driver {
public:
   Driver() : m_logger(std::cout) {}
   Driver(Logger& logger) : m_logger(logger) {}
private
   Logger m_logger;
};

Так что мой класс Driver имеет член типа Logger.Когда я вызываю конструктор без аргументов Driver(), экземпляр Driver создает свой собственный экземпляр Logger, используя std::cout.

При вызове Driver(Logger) экземпляр должен использовать уже существующий экземплярLogger передано в качестве ссылки.

Приведенный выше код компилируется с использованием g ++.Хотя я понимаю, что происходит при звонке Driver(), я не понимаю, что происходит при звонке Driver(Logger).Logger не имеет конструктора, который принимает ссылку на Logger в качестве аргумента («конструктор копирования»).Так что же выполняется при вызове Driver(Logger)?

Ответы [ 2 ]

2 голосов
/ 13 января 2012

Тривиальный конструктор копирования для Logger синтезирован для вас , если вы не объявите его самостоятельно.

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


[C++11: 12.8/7]: Если определение класса явно не объявляет конструктор копирования, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (8.4). Последний случай считается устаревшим, если у класса есть пользовательский оператор копирования или пользовательский деструктор. Таким образом, для определения класса

struct X {
   X(const X&, int);
};

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

X::X(const X& x, int i =0) { /* ... */ }

, тогда любое использование конструктора копирования X неправильно из-за неоднозначности; Диагностика не требуется.

[C++11: 12.8/8]: Неявно объявленный конструктор копирования для класса X будет иметь форму

X::X(const X&)

если

  • каждый прямой или виртуальный базовый класс B из X имеет конструктор копирования, первый параметр которого имеет тип const B& или const volatile B& и
  • для всех нестатических членов данных X, имеющих тип класса M (или их массив), каждый такой тип класса имеет конструктор копирования, первый параметр которого имеет тип const M& или const volatile M&.

В противном случае неявно объявленный конструктор копирования будет иметь вид

X::X(X&)
2 голосов
/ 13 января 2012

Когда вы создаете Driver с аргументом Logger, он берется по ссылке, и конструктор копирования Logger вызывается для инициализации m_logger, поэтому вы получаете новый Logger, который являетсякопия аргумента.Конструктор копирования предоставляется компилятором, если вы явно не сделаете Logger не подлежащим копированию, объявив конструктор копирования private.

Кажется совершенно правильным, за исключением того, что вы должны сделать аргумент logger a const ссылка;в конце концов, вы собираетесь скопировать его, а не изменять.

...