Какая польза от приведения указателя к разыменованному указателю? - PullRequest
2 голосов
/ 02 октября 2011

Этот вопрос касается объяснения кода, а не отладки кода.Код, который я использую, работает.Я использую общедоступный код, и мне было любопытно взглянуть на один из их шаблонов «массива роста», который выглядит так:

  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;
    }

, а функция srealloc выглядит следующим образом:

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;
}

Пожалуйста, пока игнорируйте функцию create .Мой главный вопрос: почему они приводят указатель и разыменование array в шаблоне?В чем преимущество этого?Что если у них просто не было *& вообще?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 02 октября 2011

Маркер & имеет много значений, два из которых вы здесь перепутали.Ты не одинок!Как оператор, это означает «адрес», который вам кажется удобным (это взято из C).Но как спецификатор типа, это означает «ссылка на», что совсем другое.Первое значение:

int x ;
int* p = &x ; // p = address of x (as in C)

Второе значение:

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

В этом примере код эквивалентен

void f (int* x) {
  (*x)++ ;
}
...
int y = 99 ;
f (&y) ; // After this call, y is equal to 100

Этот код не выглядит чистым, но это легче понять для C программистов.

Итак ... объявление функции

void f (int*& p) ;

(как в вашем примере) означает, что f может изменить значение параметра int*, передаваемого вызывающей функцией.Ваш пример кода кажется мне немного странным, потому что зачем ему возвращать новое значение array, если он может изменить параметр напрямую?Но это вопрос стиля, и я научился не обсуждать такие вопросы здесь: -)

2 голосов
/ 02 октября 2011
*&

не является «разыменованием указателя».Это ссылка на указатель.Это необходимо, чтобы функция Grow могла изменить указатель, а не только то, на что указывает указатель.Альтернативой был бы указатель на указатель, как в следующем коде.

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;
}
...