Безопасно в C#, а не в C++, простой возврат указателя / ссылки

Код C++:

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

Код C#:

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

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

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

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

7 ответов

Решение
person* NewPerson(void)
{
  person p();
  /* ... */
  return &p; //return pointer to person.
}

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

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

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

Правильный.

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

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

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

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

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

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

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

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

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

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

person x = NewPerson();

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

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

Да.

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

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

Другие вопросы по тегам