Nano Hash - криптовалюты, майнинг, программирование

Константная ссылка-обертка

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

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;
};

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

Спасибо


Ответы:


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

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

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

13.11.2011
  • Спасибо за разъяснения ! Особенно №2! :) 13.11.2011
  • Также о #1, это означает, что это вопрос с декларацией. Поскольку мы можем объявить только константную ссылку, такую ​​как const Object & x; при фактическом присвоении его указателю неизбежно выполняется ptr = &x. Моя причина верна? 13.11.2011
  • @SuprajaJayakumar: с логической точки зрения ссылка в основном называет объект. То есть внутри конструктора переданный ему объект имеет имя x (и является константным, поскольку является константной ссылкой). Поэтому вы используете x точно так же, как и переменную этого типа. Чтобы получить указатель на переменную, вы используете оператор адреса, &, и поэтому вы делаете то же самое с x. Тот факт, что ссылка также определяется с помощью символа &, логически не связан с этим. Было бы то же самое, если бы они решили использовать для этого ключевое слово ref. 13.11.2011

  • 2

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

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

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

    C++ имеет три разновидности null:

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

    3

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

    13.11.2011

    4

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

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

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

    13.11.2011
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..