#c #pointers #char
#c #указатели #символ
Вопрос:
В чем разница между этими двумя кодами?
Может кто-нибудь объяснить мне, например: #1 do, #2 do, #3 do
, пожалуйста?
У меня есть некоторые идеи, что делают эти коды, но я не уверен в этом.
void test(char *msg) {
/*3*/ msg = new char[5];
}
int main() {
/*1*/ char *msg;
/*2*/ test(msg);
}
// I think
// #2 Pass the pointer
// #3 Allocates 5 bytes char in address where the pointer points
void test(char **msg) {
/*3*/ *msg = new char[5];
}
int main() {
/*1*/ char *msg;
/*2*/ test(amp;msg);
}
// I think
// #2 Pass the address to the 4 bytes memory block where the pointer is stored
// #3 Allocates 5 bytes char to the previous 4 bytes allocates new 1 byte
Большое спасибо!
Комментарии:
1. Я бы предложил добавить строку
std::cerr << static_cast<void *>(msg) << 'n';
прямо перед и сразу после вызоваtest()
. Какие различия вы заметили? (Приведение кvoid*
тому, чтобы вы видели, что хранится,msg
а не символы, на которыеmsg
указывает.)
Ответ №1:
Я полагаю, вас смущает слишком много указателей. Указатели пугают по какой-то причине, но во многих отношениях они похожи на любую другую переменную.
Изменение указателя, переданного по значению функции, не влияет на указатель, который был передан функции.
Немного уменьшая пугающий характер вашего примера, мы получаем:
void test(std::string msg) {
msg = std::string("Hello World");
}
int main() {
std::string msg;
test(msg);
std::cout << msg; // is still an empty string !
}
void test(std::string* msg) {
*msg = std::string("Hello World");
}
int main() {
std::string msg;
test(amp;msg);
std::cout << msg; // prints hello world
}
Разница между двумя примерами (моим и вашим) заключается в том, что один передается по значению, а другой передается по ссылке (через указатель).
Более того, в вашем коде (обе версии) происходит утечка памяти, потому что вы не удаляете массив символов, выделенный via new
.
Комментарии:
1. О, итак, я передаю указатель, но по значению, поэтому он создает 5 байт символа
msg
иmsg
является указателем, но он был создан в локальной области видимости с помощью функции, не так ли? Так что вmain()
нем без изменений. Разве это не утечка памяти? Я имею в виду мой первый код.2. @JohnDoe есть два очень разных варианта вашего кода, по крайней мере, вам нужно сказать мне, о каком из них вы говорите
3. @JohnDoe да, это утечка памяти, просто заметил это и добавит примечание
Ответ №2:
Первый:
У меня есть листок бумаги с какими-то бессмысленными каракулями на нем.
Я копирую эти каракули на другой лист бумаги и вручаю его вам в качестве подарка.
Вы стираете каракули на своей собственной бумаге и записываете на ней свой адрес.
Как вы можете видеть, мой лист бумаги по-прежнему заполнен только каракулями, и я понятия не имею, где вы живете.
Второй:
У меня есть листок бумаги с какими-то бессмысленными каракулями на нем.
Я говорю вам, что этот лист бумаги есть.
Вы идете в это место, стираете каракули и записываете свой адрес.
Как вы можете видеть, на моем листе бумаги теперь есть ваш адрес.
(Короткая версия: присвоение параметру, не являющемуся ссылкой на функцию, не имеет никакого эффекта вне этой функции. В указателях нет ничего особенного.)