C ++ передача по ссылке - PullRequest
       2

C ++ передача по ссылке

0 голосов
/ 26 января 2011

Я пытаюсь передать C ++ по ссылке, используя этот простой код:

#include <iostream>
int square(int &x)
{
return x*x;
}
int main()
{
std::cout<<"Square of 4 is: "<<square(4)<<std::endl;
return 0;
}

Но, когда я пытаюсь его запустить, я получаю следующее:

enter image description here

ОБНОВЛЕНИЕ

Я получаю следующую ошибку после изменения кода на основе ответа @Pablo Santa Cruz (я только что зафиксировал часть ошибки):

enter image description here

Почему это так?

Спасибо.

Ответы [ 8 ]

10 голосов
/ 26 января 2011

Вы не можете передавать временные значения в непостоянные ссылки.

Сделать square принять const int &:

int square(const int &x)
{
    return x*x;
}
5 голосов
/ 26 января 2011

Нельзя передать константу (4), если вы ожидаете ссылку.

Вы должны передать переменную:

int n = 4;
square(n);

Имеясказал, что вы, вероятно, хотите что-то вроде этого:

void square(int &x)
{
   x = x*x;
}

Не функция, возвращающая int.

2 голосов
/ 26 января 2011

Это из-за § 8.5.3 5 C ++ 03:

Ссылка на тип « cv1 T1» инициализируется выражением типа « cv2 T2» следующим образом:
  • Если выражение инициализатора
    • является lvalue (но не битовым полем), а « cv1 T1» является эталонно-совместимым с « cv2 T2» или
    • имеет тип класса (т. Е. T2 является типом класса) и может быть неявно преобразован в lvalue типа « cv3 T3», где « cv1 T1» является ссылкой -совместим с « cv3 T3» 92) (это преобразование выбирается путем перечисления применимых функций преобразования (13.3.1.6) и выбора наилучшего с помощью разрешения перегрузки (13.3)),
    затем ссылка привязывается непосредственно к выражению инициализатора lvalue в первом случае, а ссылка привязывается к результату lvalue преобразования во втором случае. В этих случаях указывается, что ссылка привязывается напрямую к выражению инициализатора. [ Примечание: обычные преобразования lvalue-to-rvalue (4.1), массив-в-указатель (4.2) и функция-в-указатель (4.3) не нужны и поэтому подавляются, когда такие прямые привязки к lvalues ​​сделаны. ]
  • В противном случае ссылка должна быть на энергонезависимый тип const (т. Е. cv1 должно быть const).
    • Если выражение инициализатора является r-значением, с T2 - типом класса, а « cv1 T1» совместимо со ссылками с « cv2 T2», ссылка связана в одном из следующих способов (выбор определяется реализацией.
      • Ссылка привязана к объекту, представленному значением r (см. 3.10) или к подобъекту в этом объекте.
      • Создается временный объект типа « cv1 T2» [sic], и вызывается конструктор для копирования всего объекта rvalue во временный объект. Ссылка привязана к временному или подобъекту во временном.
    • В противном случае временный тип « cv1 T1» создается и инициализируется из выражения инициализатора с использованием правил инициализации нереферентной копии (8.5). Ссылка затем привязывается к временному. Если T1 связан со ссылкой на T2, cv1 должен иметь ту же квалификацию cv или большую квалификацию cv, чем cv2 ; в противном случае программа некорректна.

Выше « cv *» относится к модификаторам «const» и «volatile», а «T *» относится к именам типов. Например, const int ( cv = "const", T = "int"), const volatile std::string ( cv = "const volatile", T = "std :: string "), char* ( cv =" ", T =" char * ").

Короче говоря, rvalues ​​ разрешено связывать только с константными ссылками.

Обновление

Если ваш square теперь возвращает void (код или это не произошло), то новая ошибка заключается в том, что operator<<(std::out&, void).

нет
1 голос
/ 26 января 2011

Декларация

int square(int& x);

говорит, что функция square может изменить свой аргумент (хотя на самом деле это не так). Так что звонить square(4) нелепо: программа должна быть готова изменить номер 4.

Как уже отмечалось, вы можете изменить функцию, указав, что она не изменит свой аргумент:

int square(const int& x); // pass reference to const type
// OR
int square(int x);        // pass by value

Или вы можете вызвать исходный square, используя значение, которое можно изменить.

int square(int& x);
// ...
int num = 4;
square(num);
// now (as far as the compiler knows) num might no longer be 4!
1 голос
/ 26 января 2011

Компилятор создает временный объект для константы 4, который не может быть передан функции как неконстантная ссылка. Создайте int объект в main и передайте его функции или получите параметр функции по const-reference или по копии.

0 голосов
/ 26 января 2011

То, что вы хотите, это:

#include <iostream>
int square(int x)
{
    return(x * x);
}
int main()
{
    std::cout << "Square of 4 is: "<< square(4) << std::endl;
    return 0;
}

Вы заметили, как я избавился от & в int square(int &x)? & означает передачу по ссылке. Требуется переменная. 4 в square(4) является константой.

Используя передачу по ссылке, вы можете изменить значение x:

void square2(int &x)
{
    x = x * x;
    return;
}

Сейчас:

int x = 5;
square2(x);
// x == 25

Хотя, я не думаю, что вы этого хотите. (Вы?) Первый метод намного лучше.

0 голосов
/ 26 января 2011

Ссылочный псевдоним другой переменной. «4» не является переменной, и поэтому ваша ссылка не имеет ничего общего с псевдонимом. Поэтому компилятор жалуется.

0 голосов
/ 26 января 2011

Ссылка должна быть l-значением - в основном это то, что вы видите слева от оператора присваивания.

Итак, в основном вам сначала нужно присвоить переменную в main.Затем вы можете передать его в square.

...