Если вы изучали программирование с помощью JavaScript или даже Java, вы, вероятно, не знакомы с концепцией указателей.

Рассмотрим следующую простую программу:

Вывод кода выше:

First: 1
Second: 3

Если вам интересно, почему, тогда, пожалуйста, читайте дальше!

указатели

Ключевое отличие заключается в аргументах, передаваемых через функции addTwo и add_two. Обратите внимание, что тип аргумента не int, а int*. Это понятие, встречающееся в C/C++ и других C-подобных языках, известное как указатель. Даже если указатели вам незнакомы, вы можете узнать лежащую в их основе концепцию. По сути, указатель — это переменная, которая содержит адрес в памяти, где определен этот тип значения. Звездочка * после типа указывает, что это указатель этого типа, а не сам тип. Например, int * — это объявление не целочисленного значения, а адреса в памяти целочисленного значения. Итак, если мы посмотрим на нашу функцию add_two, то увидим, что она ожидает получить адрес, а не целочисленное значение.

Так как же нам получить значение по тому адресу, на который указывает указатель? Для этого в C/C++ мы используем так называемый оператор разыменования (который по совпадению также является *). Помещая звездочку перед переменной-указателем, мы сообщаем C/C++, чтобы он предоставил нам значение, хранящееся в этом адресе памяти. Итак, в приведенном выше примере *arg относится к значению, которое мы передали, то есть 1.

«Хорошо, но как насчет оператора «&»?»

Амперсанд &, вероятно, более знаком вам с точки зрения его использования в качестве логического оператора И в форме &&. Хотя это все еще имеет место в C/C++, одиночный & представляет собой противоположность звездочке *, поскольку он известен как оператор ссылки. Точно так же, как у нас есть * для получения значения по адресу в памяти, мы используем & для получения адреса в памяти значения. Поскольку add_two ожидал целочисленный указатель, а мы объявили second просто целочисленным значением, нам нужно передать &second, который является адресом, или указатель на значение second.

Передача по значению против передачи по ссылке

Таким образом, addTwo — это функция, которая передает аргумент по значению, а add_two передает аргумент по ссылке. Мы видим разницу между двумя, иллюстрируемую тем фактом, что выходные данные показывают, что наша переменная first не изменилась, хотя мы якобы увеличили ее на два с помощью строки arg = arg + 2, а наша переменная second изменилась.

В Java и Javascript мы знаем, что примитивные типы передаются по значению, а такие объекты, как массивы, передаются по ссылке. Мы можем видеть, как это происходит в следующих двух примерах:

В C (не C++) все передается только по значению. Это означает, что указатели абсолютно необходимы для выполнения манипуляций с массивами, как в приведенных выше примерах JS и Java. В C++ наличие указателей обеспечивает гибкость, хотя классические указатели в последнее время потеряли популярность в пользу умных указателей (мы можем вернуться к этому в другой раз!).