Я пишу функцию для загрузки текста из файла кода шейдера. Я наткнулся на что-то странное в отношении указателей, и я не могу понять, почему.
У меня есть функция с именем Load. В этой функции я копирую текст, взятый из файлового потока, в выход переменная.
static void Load(const GLchar* source_path, GLchar* output,GLint& count )
{
string code;
// loading logic here
code= vShaderStream.str(); // copying the string from the stream
count = code.length();
output = new GLchar[count];
std::size_t length = code.copy(output, count, 0);
output[length]= '\0';
}
нагрузка называется так:
for (size_t i = 0; i < d_n_fragment; i++)
{
Load(d_fragment_source_path, d_fragment_code[i], d_fragment_string_count[i]);
}
где d_fragment_code является двойным указателем Glchar **, который уже инициализирован. После загрузки функция вызывается указателем d_fragment_code [я] не содержит текста Я попытался изменить сигнатуру функции загрузки на:
static void Load(const GLchar* source_path, GLchar*& output,GLint& count )
и, таким образом, передавая указатель по ссылке. Работает после вызова функции d_fragment_code правильно хранит текст, загруженный из файла, но я не понимаю, почему указатель должен передаваться по ссылке.
Я подумал, что достаточно только передать указатель, чтобы изменить его содержимое. Я в замешательстве, не могли бы вы пролить свет на это?
Вы должны передавать указатели по ссылке, если вам нужно изменить указатель, а не объект, на который указывает указатель.
Использование двойных указателей также является аналогичным случаем.
Вот более подробная статья:
http://www.codeproject.com/Articles/4894/Pointer-to-Pointer-and-Reference-to-Pointer
output = new GLchar[count];
Это меняет то, что output
указывает на. Если вы уверены, что output
уже указывает на буфер достаточного размера, удалите эту строку.
Я подумал, что достаточно только передать указатель, чтобы изменить его содержимое.
Передачи указателя достаточно, чтобы изменить содержимое объекта (на который указывает). Это здорово, и это по сути тот же эффект, что и передача ссылки.
Но ты этого не делаешь. Вы хотите изменить сам указатель.
Подумайте, хотите ли вы передать объект в функцию таким образом, чтобы функция изменила исходный объект. Давайте назовем объект типа T и представим, что у него есть функция-член mutate
это как-то меняет (так что нам не нужно приводить реальный пример этого как T
изменения):
void foo(T& handle)
{
handle.mutate();
}
void bar(T* handle)
{
handle->mutate();
}
int main()
{
T obj;
foo(obj);
bar(&obj);
}
И то и другое foo
а также bar
выполнить то же самое, используя ссылку и указатель соответственно.
Теперь мы можем применить эту логику к чему угодно, обмениваясь различными типами для T
, Сценарий, который Вы думая о том, передает не указатель объект, указатель, чтобы изменить его:
void bar(int* handle)
{
handle->mutate();
}
int main()
{
int obj;
bar(&obj);
}
Но ситуация, которую вы на самом деле в вызовах для T
сам быть указателем, и использовать foo
скорее, чем bar
, Понятно, что это сбивает с толку!
void foo(GLint*& handle)
{
handle.mutate();
}
int main()
{
GLint* obj;
foo(obj);
}
Если это поможет, вы могли бы также написать:
void bar(GLint** handle)
{
handle->mutate();
}
int main()
{
GLint* obj;
bar(&obj);
}
что эффективно эквивалентно.
(отказ от ответственности: я не инициализировал obj
в любом из этих примеров. Вы захотите.)