Пример из главы 12:
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class sample {
char *s;
public:
sample() { s = 0; }
~sample() { if(s) delete [] s; cout << "Freeing s\n"; }
void show() { cout << s << "\n"; }
void set(char *str);
};
// Load a string.
void sample::set(char *str)
{
s = new char[strlen(str)+1];
strcpy(s, str);
}
// Return an object of type sample.
sample input()
{
char instr[80];
sample str;
cout << "Enter a string: ";
cin >> instr;
str.set(instr);
return str;
}
int main()
{
sample ob;
// assign returned object to ob
ob = input(); // This causes an error!!!!
ob.show();
return 0;
}
Цитата:
Обратите внимание на то, что деструктор класса sample вызывается три раза! В первый раз он вызывается при выходе локального объекта str из области видимости в момент возвращения из функции input(). Второй вызов деструктора~sample() происходит тогда, когда разрушается временный объект, возвращаемый функцией input(). Когда функция возвращает объект, автоматически генерируется невидимый (для вас) временный объект, который хранит возвращаемое значение. В данном случае этот объект просто представляет собой побитовую копию объекта str, который является значением, возвращаемым из функции. Следовательно, после возвращения из функции выполняется деструктор временного объекта. Поскольку область памяти, выделенная для хранения строки, вводимой пользователем, уже была освобождена (причем дважды!), при вызове функции show() на экран выведется "мусор". (Вы можете не увидеть вывод на экран"мусора". Это зависит от того, как ваш компилятор реализует динамическое выделение памяти. Однако ошибка все равно здесь присутствует.) Наконец, по завершении программы вызывается деструктор объекта ob (в функции main()).
Поступим следующим образом: уберём из определения деструктора ту инструкцию, которая порождает проблему. Новый деструктор определяется так:
~sample() { cout << "Freeing s\n"; }
Запускаем и тестируем в любой IDE:
Enter a string: abcd
Freeing s
abcd
Freeing s
Деструктор класса sample вызывается два, а не три раза. Может быть всё-таки я тут что-то неверно понял?
-- 03.01.2019, 00:36 --(Оффтоп)
По-моему это тоже важно. Герберт Шилдт является автором многочисленных пособий по разным языкам программирования. В частности он выпустил книжку
C: The Complete Reference.
В этой книге обнаружены ошибки принципиального характера. Там же даётся ещё одна ссылка с детальным разбором другой книги этого автора и сообщается следующее:
Цитата:
Readers may also appreciate Clive Feather's very helpful review of Schildt's The Annotated ANSI C Standard, which also illustrates that Schildt does not seem to have a good grasp on the C language.
Несмотря на это, Шилдт был включен в комитет по разработке стандарта C++98.