Предположим, что нам нужно передать в функцию целое число типа int. Таким образом, мы передаем в функцию sizeof(int) байт. Обычно это 4 байта (размер будет зависеть от архитектуры компьютера и компилятора). 4 байта — это немного, они будут выделены в стеке, т.к. имеет место передача по значению.
В современных задачах функциям приходится иметь дело с большими объемами данных, это могут быть десятки и сотни мегабайт. При передаче по значению в таком случае возникает 2 проблемы:
1. Каждый раз при вызове функций придется затрачивать время на копирование всего объема передаваемых данных.
2. Стек программы не всегда в состоянии вместить такой объем.
Поэтому большой объем данных передается в функцию не по значению, а по адресу. Все массивы, даже если они состоят из одного элемента, передаются по адресу.
Инициализация указателей
Указатели — это мощный инструмент. Указатели эффективно и быстро работают, но являются не слишком безопасными, т.к. вся ответственность за их использования ложится на разработчика. Не стоит забывать, что человеку свойственно ошибаться.
Представим ситуацию.
int x;
int* p;
В большинстве компиляторов C и С++ неинициализированные локальные переменные имеют случайное значение. Глобальные обнуляются. Если мы захотим разыменовать указатель и присвоить ему значение, то нужно записать следующую команду:
*p = 10;
Синтаксически все записано верно, тем не менее это выражение содержит ошибку, которая проявится в процессе выполнения - неинициализированный указатель p хранит случайный адрес. Мы можем попытаться получить значение по этому адресу и что-то туда записать. Но совсем не факт, что нам можно что-то делать с памятью по этому адресу.
Указатели нужно обнулять. Для этого есть специальное значение NULL. Для языка С это:
int* p = NULL;
В C++ обычно можно инициализировать указатель нулем.
int* p = 0;
Это возможно из-за того, что в библиотечных файлах языка, дано определение для NULL.
#define NULL (void*)0
То есть NULL — это нулевой указатель.
Давайте решим следующую задачу. Папа Карло дал Буратино 5 яблок. Злой Карабас Барабас отобрал 3 яблока. Сколько яблок осталось у Буратино?
Ответ: неизвестно. Так как нигде не сказано, сколько яблок у Буратино было изначально.
Мораль: При объявлении переменных всегда выполняйте их инициализацию.