Ниже приведен очень простой пример C ++, который показывает, что если вы хотите использовать функцию для установки указателя для указания на объект, вам нужен указатель на указатель .В противном случае, указатель будет продолжать возвращаться к нулю .
(ответ на C ++, но я считаю, что то же самое в C.)
(Также для справки: Google("передача по значению c ++") = "По умолчанию аргументы в C ++ передаются по значению. Когда аргумент передается по значению, значение аргумента копируется в параметр функции.")
Итак, мы хотимустановить указатель b
равным строке a
.
#include <iostream>
#include <string>
void Function_1(std::string* a, std::string* b) {
b = a;
std::cout << (b == nullptr); // False
}
void Function_2(std::string* a, std::string** b) {
*b = a;
std::cout << (b == nullptr); // False
}
int main() {
std::string a("Hello!");
std::string* b(nullptr);
std::cout << (b == nullptr); // True
Function_1(&a, b);
std::cout << (b == nullptr); // True
Function_2(&a, &b);
std::cout << (b == nullptr); // False
}
// Output: 10100
Что происходит в строке Function_1(&a, b);
?
«Значение»&main::a
(адрес) копируется в параметр std::string* Function_1::a
.Следовательно, Function_1::a
является указателем (то есть адресом памяти) строки main::a
.
«Значение» main::b
(адрес в памяти) копируется впараметр std::string* Function_1::b
.Поэтому в памяти теперь есть 2 из этих адресов, оба - нулевые указатели.В строке b = a;
локальная переменная Function_1::b
затем изменяется на Function_1::a
(= &main::a
), но переменная main::b
не изменяется.После вызова Function_1
, main::b
по-прежнему является нулевым указателем.
Что происходит на линии Function_2(&a, &b);
?
Обработка переменной a
такая же: внутри функции Function_2::a
является адресом строки main::a
.
Но переменная b
сейчас используетсяпередается как указатель на указатель.«Значение» &main::b
(адрес указателя main::b
) копируется в std::string** Function_2::b
.Следовательно, в Function_2 разыменование этого значения как *Function_2::b
вызовет и изменит main::b
.Таким образом, строка *b = a;
фактически устанавливает main::b
(адрес), равный Function_2::a
(= адрес main::a
), что мы и хотим.
Если вы хотите использовать функцию для изменения объекта, будь то объект или адрес (указатель), вы должны передать указатель на этот объект. То, что вы фактически передаетене может быть изменено (в области вызова), потому что сделана локальная копия.
(Исключением является то, что параметр является ссылкой, например, std::string& a
. Но обычно это const
. Обычно, еслиВы называете f(x)
, если x
является объектом, вы должны предположить, что f
не будет изменять x
. Но если x
- указатель, то вы должны предположить, чточто f
может изменить объект, на который указывает x
.)