I am writing a function to load text from shader code file. I have stumbled upon something strange regarding pointers and I cannot figure out why.
I have a function named Load. In this function I copy text, taken from a file stream, in the output variable.
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';
}
Load is called in this way:
for (size_t i = 0; i < d_n_fragment; i++)
{
Load(d_fragment_source_path, d_fragment_code[i], d_fragment_string_count[i]);
}
where d_fragment_code is a double pointer of Glchar** which is already initialized. After Load function is called the pointer d_fragment_code[i] contains no text. I tried to change the signature of the Load function to:
static void Load(const GLchar* source_path, GLchar*& output,GLint& count )
and thus passing the pointer by reference. It works, after the function is called d_fragment_code holds correctly the text loaded from the file but I don't understand why a pointer it is to be passed by reference.
I thought that passing a pointer only would suffice to change its content. I am confused, could you shed some light on it?
You should pass pointers by reference if you have to modify the pointer rather than the object that the pointer is pointing to.
Using double pointers is also a similar case.
Here is a more detailed article:
http://www.codeproject.com/Articles/4894/Pointer-to-Pointer-and-Reference-to-Pointer
output = new GLchar[count];
This changes what output
points to. If you are sure that output
already points to a buffer of sufficient size, remove this line.
I thought that passing a pointer only would suffice to change its content.
Passing a pointer suffices to change the content of the pointee (the thing pointed to). That's great, and it has essentially the same effect as passing a reference.
But you're not doing that. You want to change the pointer itself.
Consider, if you wanted to pass an object into a function such that the function altered the original object. Let's call the object's type T, and let's pretend that it has a member function mutate
that changes it somehow (so that we don't have to give a real-world example of this as T
changes):
void foo(T& handle)
{
handle.mutate();
}
void bar(T* handle)
{
handle->mutate();
}
int main()
{
T obj;
foo(obj);
bar(&obj);
}
Both foo
and bar
accomplish the same thing, using a reference and a pointer respectively.
Now we can apply this logic to anything, by exchanging various types for T
. The scenario that you're thinking of, is passing some non-pointer object, by pointer, to mutate it:
void bar(int* handle)
{
handle->mutate();
}
int main()
{
int obj;
bar(&obj);
}
But the situation you're actually in calls for T
itself to be a pointer, and to use foo
rather than bar
. It's understandable that this is confusing!
void foo(GLint*& handle)
{
handle.mutate();
}
int main()
{
GLint* obj;
foo(obj);
}
If it helps, you could also have written:
void bar(GLint** handle)
{
handle->mutate();
}
int main()
{
GLint* obj;
bar(&obj);
}
which is effectively equivalent.
(disclaimer: I didn't initialise obj
in any of those examples. You'll want to.)