Подтвердить что ты не робот

Инициализировать ссылки на члены правильно

class Temp {
    public : 
        Temp(X& x): x_(x) {}
        Temp(X& x, Y& y) : x_(x), y_(y) {}
        ...
    private:
        X& x_;
        Y& y_;
}

Я получил ошибку, потому что в случае Temp(X& x): x_(x) ссылка y_ не инициализирована. Какова обычная практика написания такого класса правильно?

4b9b3361

Ответ 1

Я предлагаю другой подход, хотя это может быть не то, что вы ищете.

Он не использует ссылочные переменные (указатели на память вместо этого), он также не использует boost, но это позволит вам сохранить оба конструктора, не тратя лишних ресурсов памяти.

#include <iostream>

class Temp
{
    public :
        Temp(int& x): x_(&x), y_(NULL) {}
        Temp(int& x, int& y) : x_(&x), y_(&y) {}
        void print() { std::cout << "*x_: " << *x_ << std::endl; }

    private:
        int* x_;
        int* y_;
};

int main()
{
    int x = 5;
    Temp tmp(x);

    tmp.print();

    return 0;
}

Ответ 2

У вас не может быть элементов ссылки, которые не инициализируются! Если это так, рассмотрите возможность обертывания ссылки в boost::optional, затем вы можете произвольно создать ссылку.

EDIT: вот подход boost::optional...

class Temp {
    public : 
        Temp(X& x): x_(x) {}
        Temp(X& x, Y& y) : x_(x), y_(y) {}
        ...
    private:
        X& x_;
        boost::optional<Y&> y_; // by default this is constructed with none_t
}

Ответ 3

Наличие элемента данных, являющегося ссылкой, является STRONG contract: Это означает, что вы НЕ МОЖЕТЕ иметь объект nullptr или undefined, ваш класс нуждается в этом объекте, объект должен существовать.

Как следствие, ваш первый конструктор нарушает этот сильный контракт и, соответственно, не может компилироваться.

Как предлагает karlphillip: вы должны использовать указатели, поскольку вы не хотите уважать такой контракт, который гарантирует, что _y всегда определяется.

Он действительно имеет ссылки как член, если ваш класс не имеет смысла без предварительного существования ссылочных объектов.

Ответ 4

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

Почему вы думаете, что хотите это сделать? Ссылка - это концептуально другое имя для уже существующей вещи. Объектами являются, ну, объекты. Вы должны быть способны создать их из цельной ткани. Иногда у них будут указатели (или экземпляры некоторого класса интеллектуальных указателей) на другие вещи, которые уже существуют, но по крайней мере сам указатель является реальными данными.

Ответ 5

У вас ссылка на y_! Ссылки должны быть инициализированы, а ваш первый конструктор - нет. Если вы не можете привязываться к y, когда класс создан, вы, вероятно, должны использовать указатель.

Ответ 6

Устранить первый конструктор или устранить вторую ссылку. Если у вас есть ссылка, вы должны немедленно ее инициализировать. Если вы должны предоставить конструктор, который по умолчанию инициализирует член Y, затем сделайте элемент Y указателем или автоматической переменной.