Если объект передается функции по значению, то в функции создается его копия. Хотя конструктор копии не вызывается, при возвращении функцией своего значения вызывается деструктор копии. Повторный вызов деструктора может привести в некоторых случаях к серьезным проблемам (например, при освобождении деструктором динамической памяти). Решает эту проблему передача объекта по ссылке. При этом копия объекта не создается, и поэтому при возвращении функцией своего значения деструктор не вызывается. Необходимо помнить: изменения объекта внутри функции влияют на исходный объект, указанный в качестве аргумента функции.
Рассмотрим версию программы, в которой объект типа myclass() передается в функцию f() по значению:
#include <iostream>
using namespace std;
class myclass
{
private:
int who;
public:
// Конструктор
myclass(int n)
{
who = n;
cout<<"Constructor: "<<who<<endl;
}
// Деструктор
~myclass()
{
cout<<"Destructor: "<<who<<endl;
}
int id()
{
return who;
}
};
// о передается по значению void f(myclass о)
void f(myclass o)
{
cout<<"ID: "<<o.id()<<endl;
}
int main()
{
myclass x(1);
f(x);
return 0;
}
Эта функция выводит на экран следующее:
Constructor: 1
ID: 1
Destructor: 1
Destructor: 1
Деструктор вызывается дважды: первый раз, когда после выполнения функции f() удаляется копия объекта 1, а второй раз – по окончании программы.
Если изменить программу так, чтобы использовать параметр-ссылку, то копия объекта не создается, и поэтому после выполнения функции f() деструктор не вызывается. Но если заменить вызов по значению, вызовом по ссылке, то получим следующий результат работы программы:
Вызов по значению: |
Вызов по ссылке: |
void f(myclass o) { cout<<"ID: "<<o.id()<<endl; }
|
void f(myclass &o) { cout<<"ID: "<<o.id()<<endl; }
|
Constructor: 1 ID: 1 Destructor: 1 Destructor: 1 |
Constructor: 1 ID: 1 Destructor: 1 |
Таким образом, вызов по ссылке позволяет избежать возможных проблем при повторном вызове деструктора.