Постоянная ссылка Обертка - PullRequest
0 голосов
/ 13 ноября 2011

Я наткнулся на следующий фрагмент кода в книге о структурах данных Марка Аллена Вайса.

template <class Object>
class Cref
{
public:
Cref ( ) : obj ( NULL ) { }
explicit Cref( const Object & x ) : obj ( &x ) {
const Object & get( ) const
{
if ( isNull( ) )
  throw NullPointerException( ) ;
else
 return *obj;
}
bool isNull( ) const
( return obj == NULL; }

private:
const Object *obj;
};

Таким образом, смысл в том, чтобы присвоить нулевой / инициализировать постоянную ссылку Но я не уверен, что понимаю следующее: 1. Мы инициализируем постоянную ссылку другой константной ссылкой x. Но почему это снова делается как obj (& x)? & в const Object & x отличается от & x в obj (& x)? Я вижу это, но не очень понятно, почему так должно быть. Просьба объяснить. 2. Метод get () - мы пытаемся вернуть константную ссылку закрытого члена obj этого класса. Это уже постоянная ссылка. Зачем возвращать * obj, а не просто obj? 3. Почему явное ключевое слово? Что может произойти, если происходит неявное преобразование типов? Может ли кто-нибудь предоставить сценарий для этого?

Спасибо

Ответы [ 4 ]

1 голос
/ 13 ноября 2011
  1. Элемент obj имеет тип Object*, но конструктор получает ссылку. Поэтому, чтобы получить указатель, необходимо применить оператор адреса &. И член является указателем, потому что он может быть NULL (установлен в конструкторе по умолчанию), а ссылки никогда не могут быть NULL.

  2. Закрытый член не константная ссылка, а poinetr для констант. Разыменовано, чтобы получить ссылку.

  3. В этом конкретном случае я также не вижу отрицательного эффекта от потенциального неявного преобразования.

1 голос
/ 13 ноября 2011

1) &x в obj(&x) используется в качестве адреса оператора.

2) Нет, это указатель.Его время равно Object *, а не Object &.

3) Чтобы исключить приведение из несовместимых типов указателей, которые могут иметь свой собственный оператор приведения типов.

C ++ имеет три варианта null:

  • NULL - устарел;используйте его только для проверки возвращаемых значений функций C, которые возвращают указатели
  • 0 - устарело;буквенный ноль определен в стандарте как нулевой указатель
  • nullptr - начиная с C ++ 11, это предпочтительный способ проверки на нулевое значение.Кроме того, nullptr_t является типобезопасным нулем.
0 голосов
/ 13 ноября 2011

1) Тип obj не является ссылкой, obj является указателем, а указатель const должен быть инициализирован с помощью адреса, поэтому должен применяться оператор адреса &, &. 2) Ссылка, которую возвращает метод get (), - это не ссылка на член класса obj, а ссылка на объект, на который указывает объект, так что вы должны использовать *, чтобы задержать его. 3) Ключевое слово явный означает, что мы отвергаем неявные преобразования, то есть мы говорим компилятору, что не делаем неявные преобразования с этим конструктором для нас.
Пример:

class Cref<Object> A;<br> Object B;<br> A=B;

Все в порядке без явного - поскольку нам нужен объект Cref с правой стороны, компилятор автоматизирует создание объекта Cref с помощью конструктора Cref (const Object & B). Но если вы добавите явное, компилятор не будет делать преобразования, будет ошибка компиляции.

0 голосов
/ 13 ноября 2011

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 хранит указатель на временный объект, который недействителен к моменту, когда функция возвращается!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...