1) Маркер &
имеет три значения:
- Оператор унарного адреса: взять адрес любого выражения lvalue, указав указатель на этот объект.
- Ссылочный символ: в объявлении означает ссылочный тип.
- Бинарный побитовый оператор И - здесь не используется
Поэтому важно знать, смотрите ли вы на объявление или выражение.
explicit Cref( const Object & x )
Здесь в объявлении параметра функции появляется символ, означающий, что тип параметра x
является ссылкой на Object
, который равен const
.
: obj ( &x ) {}
Здесь оператор используется в выражении инициализатора члена. Элемент obj
инициализируется как указатель на x
.
2) Поскольку элемент obj
на самом деле является указателем, оператор разыменования, унарный *
, необходим для получения ссылки.
3) В целом, рекомендуется использовать explicit
в любом (не копируемом) конструкторе, который может принимать ровно один аргумент. Жаль только, что по умолчанию язык не является явным и заставляет вас использовать какое-то «неявное» ключевое слово вместо этого, когда вы этого хотите. В этом случае вот одна довольно неприятная вещь, которая могла бы произойти, если бы конструктор был неявным:
Object create_obj();
void setup_ref(Cref& ref) {
ref = create_obj();
}
Нет ошибки или предупреждения компилятора, но функция setup_ref
хранит указатель на временный объект, который недействителен к моменту, когда функция возвращается!