Ошибка компиляции при отправке объекта, который ожидает получить ссылку - PullRequest
0 голосов
/ 04 мая 2020

У меня есть этот небольшой фрагмент кода, который не компилируется, и мне было интересно узнать причины, по которым конкретно pu sh (новый X) проблема?

До этого я хотел бы спросить, что на самом деле означает новый X (без идентификатора)? это создает объект X без имени идентификатора? go через конструктор вообще?

Во-вторых,

Я не могу понять всю концепцию, но pu sh - это класс шаблона, верно? Поскольку он содержит статику c T, тип T непротиворечив и не может быть изменен после отправки указанного c аргумента, первого, в данном случае int x. Это правильно?

В-третьих, после моего второго вопроса, если он правильный, то почему pu sh (y) не помечает ошибку компилятора, как pu sh (new X)? я имею в виду, что x является типом int, а y является ссылочным типом.

Я был бы очень признателен, если бы кто-то смог уточнить это для меня.

Спасибо, вот оно:

    #include <iostream>

    using namespace std;

    template <class T>
    void push(T &t) {
    static const int CAPACITY = 20;
    static T stack[CAPACITY];
    static int size = 0;
    stack[size++] = t;
    cout << size;
    };
   class X {};

   void main()
   {
   int x = 3;
   int &y = x;
   push(x);
   push(new X);
   push(y);
 }

1 Ответ

1 голос
/ 04 мая 2020

и мне было интересно узнать причины, по которым почему-то pu sh (новый X) является проблемой?

Поскольку вы объявили тип параметра функции шаблона как неконстантное значение ссылка на T. Чтобы помочь программистам избежать неправильного кода, язык не позволяет привязывать временные ссылки к неконстантным ссылкам. В вашем случае:

new X

возвращает временное значение типа X * (указатель на X), тип аргумента функции шаблона T в данном случае выводится на X *, а t теперь равно lvalue ссылка на X * или X *&, но язык не позволяет временно привязать ошибку компиляции ссылки lvalue. Ваш второй случай логически равен этому коду:

 void pushX( X *&t ); // pushX accepts reference to pointer to X

 pushX( new X ); // you cannot bind a temporary returned by `new X` to lvalue reference `t`

Это может быть легче понять, если вы используете простой тип, такой как int:

int function_returns_int();

void push_int( int &ri );


push_int( function_returns_int() ); // compilation error, function_returns_int() returns temporary

Вы можете сделать свой код скомпилированным если вы храните указатель в переменной и делаете его временным:

int main()    // main() must have return type int not void
{
   int x = 3;
   int &y = x;
   push(x);
   X *px = new X;
   push(px);
   push(y);
   delete px;
}

, но, скорее всего, вы выбрали неверный тип для аргумента.

Подробная информация о ссылках и причинах передачи int &y и почему t не будет ссылкой на ссылку, в этом случае вы можете найти здесь

Примечание: ваш код, если вы его компилируете (изменив тип t на const например) приведет к утечке памяти, но это выходит за рамки вашего вопроса

...