Why in C++ do I need to pass a pointer by referenc

2019-09-21 06:16发布

问题:

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?

回答1:

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



回答2:

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.



回答3:

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.)