Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
289 0 18:03, 26-08-2023Книга Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читать онлайн бесплатно без регистрации
Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».
Во-первых, функция expression() совершенно очевидна; она имеет один аргумент (ts) и две локальные переменные (left и t).
double expression(Token_stream& ts)
{
double left = term(ts);
Token t = ts.get();
// ...
}
Во-вторых, функция term() очень похожа на функцию expression(), за исключением того, что имеет дополнительную локальную переменную (d), которая используется для хранения результата деления (раздел case '/').
double term(Token_stream& ts)
{
double left = primary(ts);
Token t = ts.get();
// ...
case '/':
{
double d = primary(ts);
// ...
}
// ...
}
В-третьих, функция primary() очень похожа на функцию term(), за исключением того, что у нее нет локальной переменной left.
double primary(Token_stream& ts)
{
Token t = ts.get();
switch (t.kind) {
case '(':
{ double d = expression(ts);
// ...
}
// ...
}
}
Теперь у этих функций нет скрытых глобальных переменных, и они превосходно подходят для иллюстрации: у них есть аргумент и локальные переменные, и они вызывают друг друга. Возможно, вы захотите освежить память и еще раз посмотреть, как выглядят эти функции в законченном виде, но все их основные свойства, относящиеся к механизму вызова функций, уже перечислены.
При вызове функции реализация языка программирования создает структуру данных, содержащую копии всех ее параметров и локальных переменных. Например, при первом вызове функции expression() компилятор создает структуру, напоминающую показанную на рисунке.
Детали зависят от реализации, но в принципе к ним относится информация о том, что функция должна вернуть управление и некое значение в точку вызова. Такую структуру данных называют записью активации функции (function activation record), или просто активационной записью. Каждая функция имеет свою собственную запись активации. Обратите внимание на то, что с точки зрения реализации параметр представляет собой всего лишь локальную переменную.
Теперь функция expression() вызывает term(), поэтому компилятор создает активационную запись для вызова функции term().
Обратите внимание на то, что функция term() имеет дополнительную переменную d, которую необходимо хранить в памяти, поэтому при вызове мы резервируем для нее место, даже если в коде она нигде не используется. Все в порядке. Для корректных функций (а именно такие функции мы явно или неявно используем в нашей книге) затраты на создание активизационных записей не зависят от их размера. Локальная переменная d будет инициализирована только в том случае, если будет выполнен раздел case '/'.
Теперь функция term() вызывает функцию primary(), и мы получаем следующую картину.
Все это становится довольно скучным, но теперь функция primary() вызывает функцию expression().
Этот вызов функции expression() также имеет свою собственную активационную запись, отличающуюся от активационной записи первого вызова функции expression(). Хорошо это или плохо, но мы теперь попадаем в очень запутанную ситуацию, поскольку переменные left и t при двух разных вызовах будут разными. Функция, которая прямо или (как в данном случае) косвенно вызывает себя, называется рекурсивной (recursive). Как видим, рекурсивные функции являются естественным следствием метода реализации, который мы используем для вызова функции и возврата управления (и наоборот).
Итак, каждый раз, когда мы вызываем функцию стек активационных записей (stack of activation records), который часто называют просто стеком (stack), увеличивается на одну запись. И наоборот, когда функция возвращает управление, ее запись активации больше не используется. Например, когда при последнем вызове функции expression() управление возвращается функции primary(), стек возвращается в предыдущее состояние.
Когда функция primary() возвращает управление функции term(), стек возвращается в состояние, показанное ниже.
И так далее. Этот стек, который часто называют стеком вызовов (call stack), — структура данных, которая увеличивается и уменьшается с одного конца в соответствии с правилом: последним вошел — первым вышел.
Запомните, что детали реализации стека зависят от реализации языка С++, но в принципе соответствуют схеме, описанной выше. Надо ли вам знать, как реализованы вызовы функции? Разумеется, нет; мы и до этого прекрасно обходились, но многие программисты любят использовать термины “активационная запись” и “стек вызовов”, поэтому лучше понимать, о чем они говорят.
8.6. Порядок вычислений
Выполнение программы происходит инструкция за инструкцией в соответствии с правилами языка. Когда поток выполнения достигает определения переменной, происходит ее создание, т.е. в памяти выделяется память для объекта, и этот объект инициализируется. Когда переменная выходит из области видимости, она уничтожается, т.е. объект, на который она ссылалась, удаляется из памяти, и компилятор может использовать ранее занимаемый им участок памяти для других целей. Рассмотрим пример.
string program_name = "silly";
vector<string> v; // v — глобальная переменная
void f()
{
string s; // s — локальная переменная в функции f
while (cin>>s && s!="quit") {
string stripped; // stripped — локальная переменная в цикле
string not_letters;
for (int i=0; i<s.size(); ++i) // i находится в области
// видимости инструкции
if (isalpha(s[i]))
stripped += s[i];
else
not_letters += s[i];
v.push_back(stripped);
// ...
}
// ...
}
Глобальные переменные, такие как program_name и v, инициализируются до выполнения первой инструкции функции main(). Они существуют, пока программа не закончит работу, а потом уничтожаются. Они создаются в порядке следования своих определений (т.е. переменная program_name создается до переменной v), а уничтожаются — в обратном порядке (т.е. переменная v уничтожается
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор LoveRead.info.
Оставить комментарий
-
Людмила Хофман10 июнь 22:13
У меня перевернулся мир после прочтения ваших книг! Так приятно и чисто на душе, ведь по сути неважно кто с кем , а только любовь...
Долгая игра - Рейчел Рид
-
Анна08 июнь 11:28
Спасибо за новую историю жизни и любви на сайте,прочитала с удовольствием ....
Давай поженимся - Юлия Резник
-
Елена08 июнь 11:13
Прочла несколько романов этого, без сомнения, талантливого автора. Впечатление прекрасное, но хотелось бы когда-нибудь прочесть...
Предатель. Ты врал мне годами - Арина Арская
