What's the use of pointer-casting a dereferenced pointer?
This question is about code explanation, not code debugging. The code I'm using works. I'm using a public code and I was curious to look at one of their "grow array" template, which looks like this:
template <typename TYPE>
TYPE *grow(TYPE *&array, int n, const char *name)
{
if (array == NULL) return creat开发者_如何学Goe(array,n,name);
bigint nbytes = ((bigint) sizeof(TYPE)) * n;
array = (TYPE *) srealloc(array,nbytes,name);
return array;
}
and the function srealloc looks like this:
void *Memory::srealloc(void *ptr, bigint nbytes, const char *name)
{
if (nbytes == 0) {
destroy(ptr);
return NULL;
}
ptr = realloc(ptr,nbytes);
if (ptr == NULL) {
error();
}
return ptr;
}
Please disregard the create function for now. My main question is why do they pointer-cast and dereference array
in the template? What's the advantage of that? What if they just didn't have *&
at all?
Thanks!
The &
token has many meanings, two of which you have confused here. You are not alone! As an operator, it means "address of", which you seem to be comfortable with (this comes from C
). But as a type qualifier, it means "reference to", which is quite different. First meaning:
int x ;
int* p = &x ; // p = address of x (as in C)
Second meaning:
void f (int& x) { // x is a reference to an int -- its address is passed to f
x++ ;
}
...
int y = 99 ;
f (y) ; // After this call, y is equal to 100
In this example, the code is equivalent to
void f (int* x) {
(*x)++ ;
}
...
int y = 99 ;
f (&y) ; // After this call, y is equal to 100
This code doesn't look as clean, but it's easier to understand for C
programmers.
So...the function declaration
void f (int*& p) ;
(as in your example) means that f
can change the value of the int*
parameter passed by the calling function. Your sample code looks a bit screwy to me, because why does it need to return the new value of array
if it can change the parameter directly? But that is a question of style, and I have learnt not to discuss such matters here :-)
*&
is not a "pointer-dereference". It's a reference to a pointer. It's needed so the grow function can change the pointer, rather than just what the pointer points to. The alternative would have been a pointer to a pointer, like in the following code.
template <typename TYPE>
TYPE *grow(TYPE **array, int n, const char *name)
{
if ((*array) == NULL) return create((*array),n,name);
bigint nbytes = ((bigint) sizeof(TYPE)) * n;
(*array) = (TYPE *) srealloc((*array),nbytes,name);
return *array;
}
精彩评论