14.4  Передача ссылок на объекты

Если объект передается функции по значению, то в функции создается его копия. Хотя конструктор копии не вызывается, при возвращении функцией своего значения вызывается деструктор копии. Повторный вызов деструктора может привести в некоторых случаях к серьезным проблемам (например, при освобождении деструктором динамической памяти). Решает эту проблему передача объекта по ссылке. При этом копия объекта не создается, и поэтому при возвращении функцией своего значения деструктор не вызывается. Необходимо помнить: изменения объекта внутри функции влияют на исходный объект, указанный в качестве аргумента функции.

Рассмотрим версию программы, в которой объект типа 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

Таким образом, вызов по ссылке позволяет избежать возможных проблем при повторном вызове деструктора.