Язык C и его популярное заблуждение

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

void func(int *p)

{

*p =20;

}

внутренний основной()

{

целое i = 10;

int *p =

функция(p);

printf("%d",i);

}

Если вы посмотрите внимательно, вы просто передаете адрес переменной «i» в функцию, а затем разыменовываете ее, чтобы изменить значение. Другими словами, адрес переменной копируется и передается по значению в функцию. Это все равно, что сказать функции «Эй!». Здесь можно изменить значение».

Чтобы прояснить ситуацию, просто имейте в виду следующее:

  • Язык C не поддерживает передачу по ссылке
  • Язык C передает по значению без исключения. Передача указателя в качестве параметра не означает передачу по ссылке.
  • Указатель копируется и передается по значению в функцию.

Имея это в виду, давайте перейдем к нашей теме.

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

Когда переменная объявлена ​​как ссылка, она становится альтернативным именем для существующей переменной или псевдонимом. Другими словами, независимо от того, сколько ссылок вы создаете на переменную, все они имеют один и тот же адрес, но разные имена. Всегда лучше дополнить любое утверждение фрагментом кода. Попробуйте увидеть вывод приведенного ниже фрагмента кода.

внутренний основной()

{

целое число = 10;

cout ‹‹

int &ref = a;

cout ‹‹ & ref;

}

Вы наверное правильно догадались!! Оба имеют один и тот же адрес.

Переменную можно объявить как ссылку, поставив «&» в объявлении. Не путайте с "адресом" и оператором

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

В первом приближении идентификаторы ссылок = указатели без синтаксиса указателя

  • Нечто среднее между передачей указателя и передачей значения (поведение, подобное указателю, но синтаксис, подобный значению)
  • В отличие от указателей, ссылочные идентификаторы нельзя разыменовать или изменить.
  • Ссылочный идентификатор может использоваться либо как l-значение, либо как r-значение (l-значение и r-значение будут обсуждаться ниже).
  • После создания ссылки ее нельзя будет сделать ссылкой на другой объект; его нельзя переустановить. Это часто делается с помощью указателей.

Пища для размышлений: посмотрите на фрагмент кода ниже и предскажите результат:

внутренний основной()

{ int a=10,b=11;

int &ref = a;

cout ‹‹ ссылка;

ссылка = b;

cout ‹‹ ссылка;

}

Вы видите, что приведенный выше код компилируется нормально и выводит значения 10 и 11. Разве этот фрагмент кода не противоречит указанному выше пункту?

Ответ: НЕТ. Если внимательно посмотреть, ref по-прежнему является ссылкой на a — вы можете доказать это, напечатав &ref и &a и увидели, что они имеют один и тот же адрес. Что вы сделали, так это изменили a с помощью ссылки ref. Напечатайте after, и вы увидите это. Кроме того, для сравнения, если вы создадите const int &ref = a; это не позволит вам назначить это.

  • Ссылки не могут быть NULL. Указатели часто делаются NULL, чтобы указать, что они не указывают ни на что допустимое.
  • Ссылка должна быть инициализирована при объявлении. С указателями такого ограничения нет

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

целое число *a;

int &ref = *a; // теперь угадайте, каково значение a?

//фрагмент кода2

функция int&()

{

целое число =10;

вернуть a;

}

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

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

bool foobar(double &x, double& y)

{

x = x+ 10;

y= y + 10;

возвратить true;

}

внутренний основной()

{

двойные а, б;

foobar(a,b) //случай 1 работает отлично

foobar(a+5,b)//case 2 ..есть предположения?

}

Второй оператор мог вызвать ошибку компилятора, говорящую о том, что для первого аргумента ожидается l-значение. Вы могли заметить, что я использовал этот термин ранее в этом посте, говоря, что ссылочные переменные могут использоваться как l-значение и r-значение. Поэтому я думаю, что сейчас самое время ввести два новых термина lvalue и rvalue. Это чрезвычайно простые концепции, и их легко понять.

Значение L и значение R

lvalue (locator value) представляет объект, который занимает некоторое идентифицируемое место в памяти (т. е. имеет адрес).

rvalue – это выражение, которое не представляет объект, занимающий определенное место в памяти. Все литералы попадают в категорию rvalue.

целая переменная

переменная = 1;

Присваивание ожидает lvalue в качестве левого операнда, а переменная является lvalue, потому что это объект с идентифицируемой ячейкой памяти. С другой стороны, следующие недействительны:

1 = переменная; // ОШИБКА!

(переменная + 1) = 10;// ОШИБКА!

Ни константа 1, ни переменная выражения + 1 не являются lvalue (что делает их rvalue). Они не являются lvalue, потому что оба являются временными результатами выражений, которые не имеют идентифицируемого места в памяти (т. е. они могут просто находиться во временном регистре на время вычисления). Следовательно, присваивание им не имеет семантического смысла. По этой причине вызов foobar(a+5,b) не работает.

Это почти все, что нужно знать о ссылочных переменных, но есть еще много чего для изучения.

Надеюсь, вы поняли концепцию ссылочных переменных/параметров в C++.

Если у вас есть какие-либо сомнения по какой-либо из тем, обсуждаемых выше, или если вы чувствуете, что в содержании есть ошибка, напишите комментарий ниже. Давайте учиться вместе

Нравится:

Нравится Загрузка…

Первоначально опубликовано на сайте couthellloworld.wordpress.com 25 июля 2015 г.