2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Ошибка в книге Шилдт С++ базовый курс, издание 3, 2010
Сообщение03.01.2019, 03:05 


06/04/18

323
Пример из главы 12:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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()).
Поступим следующим образом: уберём из определения деструктора ту инструкцию, которая порождает проблему. Новый деструктор определяется так:
Используется синтаксис C++
~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.

 Профиль  
                  
 
 Шилдт
Сообщение03.01.2019, 09:50 
Аватара пользователя


10/10/18
754
At Home
Шилдт давно критикуется, вот, например, весьма объёмная критическая работа:

C: The Complete Nonsense
Revised for the 4th Edition
Last revision: January 13th, 2018

https://seebs.net/c/c_tcn4e.html

Ой, это же и у вас написано. Ладно, пусть остаётся.

P. S. Вообще, вполне можно изучать C++ по книгам Страуструпа, и раньше можно было, а ныне у него есть и облегчённые книги [ http://stroustrup.com/Programming/ ].

P. P. S. Хотя восприятие книг Страуструпа (по языку) может быть разным (отзыв преподавателя, также написавшего книгу по C++ /Валерий Лаптев. C++. Объектно-ориентированное программирование/): http://rsdn.org/forum/education/6245700.1

P. P. P. S. Очень хороши как дополнение к книгам Страуструпа Комментарии Сергея Деревяго, в процессе их написания Сергей переписывался со Страуструпом. http://ders.stml.net/cpp/

 Профиль  
                  
 
 Re: Ошибка в книге Шилдт С++ базовый курс, издание 3, 2010
Сообщение03.01.2019, 10:25 
Заслуженный участник


28/04/09
1933
Qlin в сообщении #1365569 писал(а):
Запускаем и тестируем в любой IDE:
Таким образом тестировать поведение кода бессмысленно. Необходимо либо читать стандарт, либо сравнивать поведение разных компиляторов с выкрученными на максимум настройками соответствия стандарту (если наблюдаемое поведение одинаково, то, скорее всего, именно оно предполагается стандартом; в противном случае обязательно необходимо обратиться к тексту стандарта).
В данном случае Вы столкнулись с т.н. copy elision. В стандарте описана данная возможность, но стандарт не требует, чтобы компиляторы обязательно реализовывали её. Т.е. компиляторы могут использовать эту возможность в целях оптимизации. По умолчанию многие компиляторы реализуют copy elision, чтобы её отключить, например, в clang++ и g++ необходимо использовать ключ командной строки -fno-elide-constructors:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>


struct Foo
{
    ~Foo()
    {
        std::cout << "~Foo::Foo()" << std::endl;
    }
};

Foo bar()
{
    return Foo();
}


int main()
{
    std::cout << __cplusplus << std::endl;
   
    Foo foo;
   
    foo = bar();
}
 
Как можно видеть, деструктор вызывается именно три раза во всех случаях, кроме C++17. Дело в том, что в последнем на данный момент стандарте языка появилось такое понятие как guaranteed copy elision, и copy elision стал обязательным в некоторых случаях. Резюмируя, можно сказать, что Шилдт отчасти прав, но он утаивает довольно важную информацию от читателей.

 Профиль  
                  
 
 Re: Ошибка в книге Шилдт С++ базовый курс, издание 3, 2010
Сообщение03.01.2019, 14:36 


06/04/18

323
EtCetera, спасибо за ответ.
EtCetera в сообщении #1365594 писал(а):
Резюмируя, можно сказать, что Шилдт отчасти прав, но он утаивает довольно важную информацию от читателей.
Да, по сути он утаивает, что этот его код не является переносимым.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group