Другими словами, в обоих объектах (в оригинале и его копии) член данных
В действительности дела обстоят еще хуже. По завершении программы разрушается объект
Возможно, читатель уже догадался, что один из путей решения проблемы, связанной с разрушением (еще нужных) данных деструктором объекта, являющегося параметром функции, состоит не в передаче самого объекта, а в передаче указателя на него или ссылки. В этом случае копия объекта не создается; следовательно, по завершении функции деструктор не вызывается. Вот как выглядит, например, один из способов исправления предыдущей программы.
// Одно из решений проблемы передачи объектов.
#include
#include
using namespace std;
class myclass {
int *p;
public:
myclass(int i);
~myclass();
int getval() { return *p; }
};
myclass::myclass(int i)
{
cout << "Выделение памяти, адресуемой указателем p.\n";
р = new int;
*p = i;
}
myclass::~myclass()
{
cout <<"Освобождение памяти, адресуемой указателем p.\n";
delete p;
}
/* Эта функция HE создает проблем. Поскольку объект ob теперь передается по ссылке, копия аргумента не создается, а следовательно, объект не выходит из области видимости по завершении функции display().
*/
void display(myclass &ob)
{
cout << ob.getval() << '\n';
}
int main()
{
myclass a(10);
display(a);
return 0;
}
Результаты выполнения этой версии программы выглядят гораздо лучше предыдущих.
Выделение памяти, адресуемой указателем р.
10
Освобождение памяти, адресуемой указателем р.
Как видите, здесь деструктор вызывается только один раз, поскольку при передаче по ссылке аргумента функции
Передача объекта по ссылке — прекрасное решение описанной проблемы, но только в случаях, когда ситуация позволяет принять его, что бывает далеко не всегда. К счастью, есть более общее решение: можно создать собственную версию конструктора копии. Это позволит точно определить, как именно следует создавать копию объекта и тем самым избежать описанных выше проблем. Но прежде чем мы займемся конструктором копии, имеет смысл рассмотреть еще одну ситуацию, в обработке которой мы также можем выиграть от создания
Если объекты можно передавать функциям, то
// Использование функции, которая возвращает объект.
#include
#include
using namespace std;
class sample {
char s[80];
public:
void show() { cout << s << "\n"; }
void set(char *str) { strcpy(s, str); }
};
// Эта функция возвращает объект типа sample.
sample input()
{
char instr[80];
sample str;
cout << "Введите строку: ";
cin >> instr;
str.set(instr);
return str;
}
int main()
{
sample ob;
// Присваиваем объект, возвращаемый
// функцией input(), объекту ob.
ob = input();
ob.show();
return 0;
}