2015-01-30 3 views
-2

Я пишу функцию для загрузки текста из файла кода шейдера. Я наткнулся на что-то странное в отношении указателей, и я не могу понять, почему.Почему в C++ мне нужно передать указатель ссылкой, чтобы изменить выделенный контент?

У меня есть функция с именем 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 [i] не содержит текста. Я попытался изменить подпись функции нагрузки на:

static void Load(const GLchar* source_path, GLchar*& output,GLint& count) 

и, таким образом, передать указатель по ссылке. Он работает после того, как функция называется . D_fragment_code правильно сохраняет текст, загруженный из файла, но я не понимаю, почему указатель должен быть передан по ссылке.

Я думал, что передать указатель достаточно, чтобы изменить его содержимое. Я смущен, не могли бы вы пролить свет на него?

+3

Вы не только изменить содержание, изменить указатель здесь: 'выход = новый GLchar [число];' –

ответ

2

Я думал, что передать указатель достаточно, чтобы изменить его содержимое.

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

Но вы этого не делаете. Вы хотите изменить сам указатель.

Рассмотрите, если вы хотите передать объект в функцию, так что функция изменила исходный объект. Назовем тип Т объекта, и давайте делать вид, что он имеет функцию-член 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 ни в одном из этих примеров Вы хотите)

+0

Вы можете указать * где * OP фактически меняет сам указатель. Кажется, они не знают. – Angew

+0

@Angew: Я не согласен –

3
output = new GLchar[count]; 

Это меняет то, что output указывает. Если вы уверены, что output уже указывает на буфер достаточного размера, удалите эту строку.

+0

Вы не объяснили проблему или не объяснили, почему мы передаем указатели по ссылке или объясняем, почему факт, что это был указатель в первую очередь, был недостаточным. –