Цей фрагмент коду:
int& func1()
{
int i;
i = 1;
return i;
}
не працюватиме, тому що ви повертаєте псевдонім (посилання) на об’єкт, термін експлуатації обмежений обсягом виклику функції. Це означає, що колись func1()
повертається, int i
вмирає, роблячи повернення посилання з функції непридатним, оскільки тепер воно посилається на об'єкт, який не існує.
int main()
{
int& p = func1();
/* p is garbage */
}
Друга версія працює, тому що змінна розміщена у вільному магазині, який не пов'язаний з терміном дії виклику функції. Однак ви несете відповідальність за delete
надання виділених int
.
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}
Як правило, ви загорнете вказівник у якийсь клас RAII та / або фабричну функцію, щоб вам не доведеться delete
його самостійно.
В будь-якому випадку ви можете просто повернути саме значення (хоча я усвідомлюю, що приклад, який ви подали, мабуть, надуманий):
int func3()
{
return 1;
}
int main()
{
int v = func3();
// do whatever you want with the returned value
}
Зауважте, що цілком чудово повертати великі об'єкти так само, як func3()
повертає примітивні значення, тому що майже кожен компілятор нині реалізує певну форму оптимізації повернення :
class big_object
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};
big_object func4()
{
return big_object(/* constructor arguments */);
}
int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}
Цікаво, що прив’язання тимчасового до посилання const є цілком законним C ++ .
int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}
int& i = * new int;