Я делаю что-то не так (ссылки в C ++)? - PullRequest
5 голосов
/ 13 июня 2010

Я играл со ссылками (у меня все еще есть проблемы в этом отношении).

1- Я хотел бы знать, является ли это приемлемым кодом:

int & foo(int &y)
{
    return y;  // is this wrong?
}

int main()
{
    int x = 0;    
    cout << foo(x) << endl;

    foo(x) = 9;   // is this wrong?
    cout << x << endl;

    return 0;
}

2- Также это из примера экзамена:

Week & Week::highestSalesWeek(Week aYear[52])
{
  Week max = aYear[0];
  for(int i = 1; i < 52; i++)
  {
    if (aYear[i].getSales() > max.getSales())
      max = aYear[i];
  }
  return max;
}

Он спрашивает об ошибке в этом коде, а также о том, как ее исправить.

Я предполагаю, что он возвращает локальныйссылка.Исправление:

Week & max = aYear[0];

Это правильно / достаточно?

Ответы [ 3 ]

5 голосов
/ 13 июня 2010

Первый правильный.

Для второго существует бесконечное количество решений :), но это будет мое:

Week Week::highestSalesWeek(Week aYear[52]) // return a copy of the week
{ 
  Week max = aYear[0]; 
  for(int i = 1; i < 52; i++) 
  { 
    if (aYear[i].getSales() > max.getSales()) max = aYear[i]; 
  } 
  return max; 
} 

Если max - это ссылкавы бы каждый раз изменяли первый элемент aYear:

max = aYear[i]

Также вы можете использовать указатель для возврата ссылки на неделю:

Week & Week::highestSalesWeek(Week aYear[52])
{ 
  Week* max = &aYear[0]; 
  for(int i = 1; i < 52; i++) 
  { 
    if (aYear[i].getSales() > max->getSales()) max = &aYear[i]; 
  } 
  return *max; 
} 
2 голосов
/ 13 июня 2010

В ссылках всегда важно убедиться, что ссылка не относится к объекту, который вышел из области видимости.

В этом проблема вашего второго примера:

Week & Week::highestSalesWeek(Week aYear[52])
{
  Week max = aYear[0];
  return max;
}

max - это автоматическая переменная, локальная для этого метода.Когда этот метод выходит из области видимости, max выходит из области видимости, и теперь ваш код имеет ссылку на случайную память.

Поскольку ваш код хочет продолжать переназначать max, вы не можете использовать ссылку(поскольку после первоначального присваивания вы можете изменять только то, на что ссылается, а не саму ссылку).Вам необходимо отслеживать фактическую часть aYear, на которую вы хотите вернуть ссылку.Два предложения.

// By pointer
Week & Week::highestSalesWeek(Week aYear[52])
{
  Week *max = &aYear[0];
  ...;
  return *max;
}

// By index
Week & Week::highestSalesWeek(Week aYear[52])
{
  size_t max_idx = 0;;
  ...;
  return aYear[max_idx];
}    
1 голос
/ 13 июня 2010

Чтобы ответить на ваши вопросы:

foo(x) = 9;   // is this wrong?

Я бы сказал, да, это неправильно, потому что это не имеет смысла, хотя это синтаксически допустимо. А что касается вашего «экзаменационного» вопроса (кто задает этот материал?):

Week & Week::highestSalesWeek(Week aYear[52])
{
  Week max = aYear[0];
  for(int i = 1; i < 52; i++)
  {
    if (aYear[i].getSales() > max.getSales()) max = aYear[i];
  }
  return max;
}

Что ж, указывать размерность массива для параметра бессмысленно, и в коде, очевидно, должен использоваться вектор. И исправление должно быть в сигнатуре функции:

Week  Week::highestSalesWeek(Week aYear[52])

Другими словами - вернуть значение. Вы должны почти всегда возвращать значения, а не ссылки - ссылки предназначены для параметров функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...