Безопасно в 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
человек в куче, а затем вернуть ссылку на это.