Безопасно в C #, а не в C ++, простой возврат указателя / ссылки - PullRequest
4 голосов
/ 10 декабря 2011

C ++ code:

person* NewPerson(void)
{
  person p;
  /* ... */
  return &p; //return pointer to person.
}

C # code:

person NewPerson()
{
  return new person(); //return reference to person.
}

Если я правильно понимаю, пример на C ++ не подходит, потому что p выйдет изобласть действия, и функция возвратит дикий указатель (висячий указатель).

Пример на C # в порядке, поскольку анонимный новый человек будет оставаться в области действия до тех пор, пока имеется ссылка на него.(Вызывающая функция получает один.)

Правильно ли я понял?

Ответы [ 7 ]

4 голосов
/ 10 декабря 2011

Пример на C ++ не подходит, потому что 'p' выйдет из области видимости, а функция вернет недопустимый указатель.

Правильно.

Пример в C # подходит, потому что анонимный «новый человек» будет оставаться в области действия до тех пор, пока на него есть какая-либо ссылка.

Это более или менее правильно, но ваша терминология не совсем верна. Область действия в C # - это область текста, в которой можно использовать безусловное имя . Объект здесь не имеет имени. Срок службы - это период времени выполнения, в течение которого место хранения гарантированно будет действительным. Область и срок действия связаны; когда элемент управления оставляет код, связанный с областью действия, время жизни локальных элементов, объявленных в этой области, обычно может заканчиваться. (Существуют ситуации, когда время жизни местных жителей больше или меньше, чем время, когда контроль находится в их сфере действия.)

Также обратите внимание, что это не любая ссылка на объект Person, который поддерживает его. Ссылка должна быть с корнем . Вы можете иметь два объекта Person, которые ссылаются друг на друга, но в противном случае они недоступны; тот факт, что у каждого есть ссылка, не поддерживает их жизнь; одна из ссылок должна быть укоренена.

2 голосов
/ 10 декабря 2011
person* NewPerson(void)
{
  person p();
  /* ... */
  return &p; //return pointer to person.
}

p - это не person, см. самый неприятный анализ .Таким образом, вы получите ошибку компилятора.

В остальном, да, вы правы.

2 голосов
/ 10 декабря 2011

Правила области видимости в этом примере аналогичны, но в C #, если возвращаемое значение назначено чему-либо, оно не будет собираться мусором, пока что-то содержит ссылку на него.Если это не назначено чему-то, ничто не содержит ссылку на него, и это будет сборка мусора в следующий раз, когда сборщик выполнит

1 голос
/ 10 декабря 2011

Да, вы правильно поняли.

Тем не менее, в C ++ вы бы действительно сделали это

person NewPerson()
{
  person p;
  /* ... */
  return p; //return person.
}

и будь уверен, что при звонке

person x = NewPerson();

компилятор оптимизирует копирование возвращаемого значения.

1 голос
/ 10 декабря 2011

В C ++ это 'p' будет жить в стеке и, таким образом, будет перекрыто при возврате функции.В C # сборщик мусора знает, что он не должен забивать его до тех пор, пока не будет потеряна последняя ссылка.

(здесь используется "clobber" свободно ...: p)

0 голосов
/ 10 декабря 2011

Это не будет работать в C ++, потому что вы возвращаете ссылку на временный объект, который будет уничтожен после завершения функции. Вам нужно создать new человека в куче, а затем вернуть ссылку на него.

0 голосов
/ 10 декабря 2011

Правильно ли я понял это?

Да.

Кстати: на C ++ человек p ();объявляет функцию и не будет вызывать ctor человека по умолчанию.Просто напишите человеку р;

...