a * returnnew() {
a retval;
return(&retval);
}
Здесь retval
имеет автоматическую продолжительность хранения, что означает, что язык автоматически уничтожит его, когда он выйдет из области видимости.Адрес, который вы возвратили, ссылается на объект, который больше не существует, и попытка использовать возвращаемое значение будет ошибкой.
Если вы хотите, чтобы время жизни объекта контролировалось вами, вы должны использовать оператор new для его создания.
a* returnnew()
{
a* retval = new a();
return retval;
}
Теперь у вас есть полный контроль над временем жизни этого a
.Он будет жить до тех пор, пока вы явно не delete
его или ваша программа не закончится.
Вы также можете придумать значимую семантику копирования для вашего класса a
и вернуть ее по значению, и в этом случае вызывающая сторона получит свою собственную копию, отличную от оригинала.Тогда ваш абонент не заботится, когда оригинал уходит.
class a
{
int * p;
public:
a(a const& rhs)
{
p = new int(rhs.p)
}
a()
{
p = new int;
}
~a()
{
delete p;
}
};
Теперь вы можете создать новый a
как копию существующего a
.Таким образом, ваша функция может затем вернуть a
по значению, например, так:
a returnnew()
{
a retval;
return retval;
}
Здесь время жизни retval закончится, когда функция вернется, и оно будет автоматически уничтожено языком, и ресурсы не будутутечка.И у вашего абонента будет своя копия, со своим временем жизни.
По моему опыту, большинство классов должны иметь разумную семантику копирования, и вы не должны бояться передавать и возвращать их по значению.Так проще, и вы избежите проблем с висящими указателями.
Одна из самых сильных сторон C ++ - это то, что деструкторы автоматически вызываются языком, когда объекты с длительностью автоматического хранения выходят из области видимости.Если вы обеспечите, чтобы каждый ресурс в вашей программе принадлежал такому объекту, вам будет гораздо сложнее просочиться.