Почему передача указателя по ссылке после передачи его по значению указывает на исходную ячейку памяти?

Я работаю с SWIG, чтобы обернуть некоторый код C++ в Python. Функция С++, которую я оборачиваю, определяется как:

template <typename T>
void getData(const std::string& fileName, T*& data);

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

Теперь мы подошли к моему вопросу, упаковка SWIG дала мне следующую функцию:

void wrap_getData(const std::string& fileName, T* data) {
     getData(fileName, data);
}

И это называется использованием:

unsigned char* data = new unsigned char[dataSizeInFile]
wrap_getData(fileName, data)

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

Например, исходный адрес памяти указателя (&ptr) = 0x000000000c840070, тогда внутри функции wrap_getData адрес памяти указателя данных (&ptr) равен 0x00000000002393e8, что, как и ожидалось, отличается, поскольку указатель копируется. Но теперь, когда я передаю этот указатель по ссылке фактической функции getData, адрес памяти (&ptr) снова равен 0x000000000c840070, чего я не ожидал, я ожидал, что он останется 0x00000000002393e8, так как копия передается по ссылке. Почему это происходит?


person Geert    schedule 23.03.2015    source источник
comment
Пожалуйста, отредактируйте свой вопрос, чтобы более четко определить, что вы подразумеваете под адресом в любой конкретной точке. Использование таких терминов, как адрес указателя, означает &ptr, а адрес, на который указывает указатель, означает просто ptr. Прямо сейчас действительно неясно, что вы имеете в виду, когда, и какое из двух значений не соответствует вашим ожиданиям.   -  person aruisdante    schedule 23.03.2015
comment
Перейдите сюда и отредактируйте то, что вы видите, чтобы оно соответствовало тому, что вы пытаетесь объяснить: coliru.stacked- crooked.com/a/61d21d0af7c9b1e2   -  person PaulMcKenzie    schedule 23.03.2015
comment
PaulMcKenzie, я отредактировал его, поведение в Coliru Viewer действительно такое, как я и ожидал (coliru.stacked -crooked.com/a/5080224fe682ebe0), но это не то поведение, которое я наблюдаю в Visual Studio 2012. Поэтому я не уверен, почему оно ведет себя так, как ожидалось, а не в моей системе.   -  person Geert    schedule 23.03.2015
comment
@Geert - Ну, у меня есть VS 2008 и VS 2013, и поведение такое же, как в примере с Coliru.   -  person PaulMcKenzie    schedule 23.03.2015


Ответы (2)


вы передали указатель. в функции был создан новый указатель, но он показывает тот же объект. и через указатель этот объект (на который указывал указатель) можно было изменить в функции. после функции указатель, созданный с помощью функции, уничтожался/освобождался. исходное местоположение указателя в памяти все время оставалось неизменным, таким же, как и значение, на которое указывал указатель.

вот что я думаю. Возможно, я слишком быстро прочитал ваш вопрос.

перед вызовом getData(fileName, data); указатель data находится, например, на адресе «a_17», и его значение, например, «v_22», при вызове функции параметр функции T*& data создается и получает то же значение, что и аргумент data. поэтому он получает новый адрес (пример «a_34») и его значение «v_22».

если вы хотите перейти туда, куда указывает указатель с помощью функции, просто передайте указатель на указатель.

редактировать: добавлен рисунок: ссылка вот как я это вижу. Признаюсь, я новичок в этом "*&" в параметрах функции, предпочитаю использовать указатели и указатели указателям.

person iNyuu    schedule 23.03.2015
comment
Не совсем уверен, что вы имеете в виду. Когда я впервые передаю указатель (адрес памяти a_17), создается копия (адрес памяти a_18). Когда я передаю эту копию по ссылке, я ожидаю, что эта ссылка покажет a_18, а не a_17, верно? - person Geert; 23.03.2015
comment
имея, например, char* data, затем вызов {{ f_data(data); где функция void f_data(char*& in_data) }} аналогичен тому же char* data, который вы бы вызвали {{ f_data(&data);, который является недействительным f_data(char ** in_data), но тогда вам пришлось бы использовать *in_data в функции. }} function parameterchar*& in_data означает ссылку на указатель на char. это означает, что если мы изменим in_data, мы изменим данные. - person iNyuu; 23.03.2015
comment
Привет iNyuu, извини, я думаю, что мы не на той же странице. Пожалуйста, смотрите мой комментарий в ответ на комментарий Пола Маккензи, он содержит код, который я ожидал. - person Geert; 23.03.2015

Это работает случайно. Если вы удалите массив, а затем сразу создадите новый точно такого же размера, велика вероятность, что он будет использовать тот же адрес памяти. Остальное поведение нормальное.

person Geert    schedule 23.03.2015