Error: неверная инициализация ссылки типа 'int &' из выражения типа 'const int'

Это несвязанный вопрос о коде в этом вопросе относительно следующей функции шаблона.

template <class T>
class Object : public Container {
public:
    T& object;

    Object(const T& obj) : object(obj) {}
};

Это код, вызывающий конструктор:

template <class T>
void Array::add_element(const T& element)
{
    vec.push_back(new Object<T>(element));
}

Этот код компилируется отлично, но как только я добавляю строку в main, которая ее вызывает:

Array array;
int i = 3;
array.add_element(i);

Я получаю предупреждение о компиляторе: error: invalid initialization of reference of type 'int&' from expression of type 'const int'.

Что это значит? Я передал int дюйм. Разве он не должен автоматически превращаться в const int& для меня? Почему компилятор жалуется?

Ответ 1

obj является ссылкой на константу. object - это неконстантная ссылка.

Вы не можете инициализировать ссылку, отличную от const, из ссылки const, поскольку это может привести к тому, что в первую очередь будет иметь ссылку на const.

Если вы хотите, чтобы ваш экземпляр object мог модифицировать int, переданный его конструктору, конструктор должен взять неконстантную ссылку. Если вы этого не сделаете, то элемент данных должен быть константной ссылкой.

В любом случае вы сами сохраняете проблемы, если используете new для выделения объектов, имеющих ссылки в качестве элементов данных. Ваша проблема в том, что вы удалите object до того, как i выходит за рамки (или, во всяком случае, убедитесь, что object не использует свой член object после i выходит за пределы области видимости.

Ответ 2

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

const int myConstNumber = 4;
Object<int> intObj(myConstNumber);

intObj.object = 3; // you have indirectly modified the value of myConstNumber

C++ не позволяет вам сделать это. Вы можете сделать копию объекта или добавить const к вашему атрибуту.

template <class T>
class Object : public Container {
public:
    T object; // valid

или же

template <class T>
class Object : public Container {
public:
    const T& object; // valid

в этом случае вы не сможете изменить объект