Главная » Просмотр файлов » Б. Страуструп - Язык программирования С++

Б. Страуструп - Язык программирования С++ (1119446), страница 53

Файл №1119446 Б. Страуструп - Язык программирования С++ (Б. Страуструп - Язык программирования С++) 53 страницаБ. Страуструп - Язык программирования С++ (1119446) страница 532019-05-09СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 53)

Однако, для интерпретации значений классов могут использоваться вместофункций-членов литералы основных типов. Общим средством для построения таких значений служатконструкторы с единственным параметром. Если конструктор достаточно простой и реализуетсяподстановкой, вполне разумно представлять его вызов как литерал. Например, с учетом описаниякласса complex в <complex.h> в выражении zz1*3+zz2*complex(1,2) произойдет два вызова функций, ане пять. Две операции * приведут к вызову функции, а операция + и вызовы конструктора дляпостроения complex(3) и complex(1,2) будут реализованы подстановкой.7.5 Большие объектыПри выполнении любой бинарной операции для типа complex реализующей эту операцию функциибудут передаваться как параметры копии обоих операндов.

Дополнительные расходы, вызванныекопированием двух значений типа double, заметны, хотя по всей видимости допустимы. К сожалениюпредставление не всех классов является столь удобно компактным. Чтобы избежать избыточногокопирования, можно определять функции с параметрами типа ссылки:class matrix {double m[4][4];public:matrix();friend matrix operator+(const matrix&, const matrix&);friend matrix operator*(const matrix&, const matrix&);};Ссылки позволяют без излишнего копирования использовать выражения с обычными арифметическимиоперациями и для больших объектов. Указатели для этой цели использовать нельзя, т.к. невозможнопереопределить интерпретацию операции, если она применяется к указателю. Операцию плюс дляматриц можно определить так:matrix operator+(const matrix& arg1, const& arg2){matrix sum;for (int i = 0; i<4; i++)for (int j=0; j<4; j++)sum.m[i] [j] = arg1.m[i][j] + arg2.m[i][j];return sum;}Здесь в функции operator+() операнды выбираются по ссылке, а возвращается само значение объекта.Более эффективным решением был бы возврат тоже ссылки:class matrix {// ...189Бьерн Страуструп.Язык программирования С++friend matrix& operator+(const matrix&, const matrix&);friend matrix& operator*(const matrix&, const matrix&);};Это допустимо, но возникает проблема с выделением памяти.

Поскольку ссылка на результат операциибудет передаваться как ссылка на возвращаемое функцией значение, оно не может бытьавтоматической переменной этой функции. Поскольку операция может использоваться неоднократно водном выражении, результат не может быть и локальной статической переменной. Как правило,результат будет записываться в отведенный в свободной памяти объект. Обычно бывает дешевле (позатратам на время выполнения и память данных и команд) копировать результирующее значение, чемразмещать его в свободной памяти и затем в конечном счете освобождать выделенную память. К томуже этот способ проще запрограммировать.7.6 Присваивание и инициализацияРассмотрим простой строковый класс string:struct string {char* p;int size;// размер вектора, на который указывает pstring(int size) { p = new char[size=sz]; }~string() { delete p; }};Строка - это структура данных, содержащая указатель на вектор символов и размер этого вектора.Вектор создается конструктором и удаляется деструктором.

Но как мы видели в $$5.5.1 здесь могутвозникнуть проблемы:void f(){string s1(10);string s2(20)s1 = s2;}Здесь будут размещены два символьных вектора, но в результате присваивания s1 = s2 указатель наодин из них будет уничтожен, и заменится копией второго. По выходе из f() будет вызван для s1 и s2деструктор, который дважды удалит один и тот же вектор, результаты чего по всей видимости будутплачевны.

Для решения этой проблемы нужно определить соответствующее присваивание объектовтипа string:struct string {char* p;int size;// размер вектора, на который указывает pstring(int size) { p = new char[size=sz]; }~string() { delete p; }string& operator=(const string&);};string& string::operator=(const string& a){if (this !=&a) {// опасно, когда s=sdelete p;p = new char[size=a.size];strcpy(p,a.p);}return *this;}При таком определении string предыдущий пример пройдет как задумано.

Но после небольшогоизменения в f() проблема возникает снова, но в ином обличии:190Бьерн Страуструп.void f(){string s1(10);string s2 = s1;}Язык программирования С++// инициализация, а не присваиваниеТеперь только один объект типа string строится конструктором string::string(int), а уничтожаться будетдве строки. Дело в том, что пользовательская операция присваивания не применяется кнеинициализированному объекту. Достаточно взглянуть на функцию string::operator(), чтобы понятьпричину этого: указатель p будет тогда иметь неопределенное, по сути случайное значение.

Какправило, в операции присваивания предполагается, что ее параметры проинициализированы. Дляинициализации типа той, что приведена в этом примере это не так по определению. Следовательно,чтобы справиться с инициализацией нужна похожая, но своя функция:struct string {char* p;int size;// размер вектора, на который указывает pstring(int size) { p = new char[size=sz]; }~string() { delete p; }string& operator=(const string&);string(const string&);};string::string(const string& a){p=new char[size=sz];strcpy(p,a.p);}Инициализация объекта типа X происходит с помощью конструктора X(const X&).

Мы не перестаемповторять, что присваивание и инициализация являются разными операциями. Особенно это важно втех случаях, когда определен деструктор. Если в классе X есть нетривиальный деструктор, например,производящий освобождение объекта в свободной памяти, вероятнее всего, в этом классе потребуетсяполный набор функций, чтобы избежать копирования объектов по членам:class X {// ...X(something);X(const X&);operator=(const X&);~X();//////////конструктор, создающий объектконструктор копированияприсваивание:удаление и копированиедеструктор, удаляющий объект};Есть еще два случая, когда приходится копировать объект: передача параметра функции и возврат еюзначения.

При передаче параметра неинициализированная переменная, т.е. формальный параметринициализируется. Семантика этой операции идентична другим видам инициализации. Тожепроисходит и при возврате функцией значения, хотя этот случай не такой очевидный. В обоих случаяхиспользуется конструктор копирования:string g(string arg){return arg;}main(){string s = "asdf";s = g(s);}Очевидно, после вызова g() значение s должно быть "asdf". Не трудно записать в параметр s копию191Бьерн Страуструп.Язык программирования С++значения s, для этого надо вызвать конструктор копирования для string. Для получения еще одной копиизначения s по выходе из g() нужен еще один вызов конструктора string(const string&). На этот разинициализируется временная переменная, которая затем присваивается s.

Для оптимизации одну, ноне обе, из подобных операций копирования можно убрать. Естественно, временные переменные,используемые для таких целей, уничтожаются надлежащим образом деструктором string::~string() (см.$$R.12.2).Если в классе X операция присваивания X::operator=(const X&) и конструктор копирования X::X(const X&)явно не заданы программистом, недостающие операции будут созданы транслятором.

Эти созданныефункции будут копировать по членам для всех членов класса X. Если члены принимают простыезначения, как в случае комплексных чисел, это, то, что нужно, и созданные функции превратятся впростое и оптимальное поразрядное копирование. Если для самих членов определеныпользовательские операции копирования, они и будут вызываться соответствующим образом:class Record {string name, address, profession;// ...};void f(Record& r1){Record r2 = r1;}Здесь для копирования каждого члена типа string из объекта r1 будет вызываться string::operator=(conststring&).

В нашем первом и неполноценном варианте строковый класс имеет член-указатель идеструктор. Поэтому стандартное копирование по членам для него почти наверняка неверно.Транслятор может предупреждать о таких ситуациях.7.7 ИндексацияОператорная функция operator[] задает для объектов классов интерпретацию индексации. Второйпараметр этой функций (индекс) может иметь произвольный тип. Это позволяет, например, определятьассоциативные массивы. В качестве примера можно переписать определение из $$2.3.10, гдеассоциативный массив использовался в небольшой программе, подсчитывающей число вхожденийслов в файле. Там для этого использовалась функция. Мы определим настоящий тип ассоциативногомассива:class assoc {struct pair {char* name;int val;};pair* vec;int max;int free;assoc(const assoc&);assoc& operator=(const assoc&);public:assoc(int);int& operator[](const char*);void print_all();};// предотвращает копирование// предотвращает копированиеВ объекте assoc хранится вектор из структур pair размером max.

В переменной free хранится индекспервого свободного элемента вектора.Чтобы предотвратить копирование объектов assoc, конструктор копирования и операция присваиванияописаны как частные. Конструктор выглядит так:assoc::assoc(int s){192Бьерн Страуструп.Язык программирования С++max = (s<16) ? 16 : s;free = 0;vec = new pair[max];}В реализации используется все тот же неэффективный алгоритм поиска, что и в $$2.3.10. Но теперь,если вектор переполняется, объект assoc увеличивается:#include <string.h>int& assoc::operator[](const char* p)/*работает с множеством пар (структур pair):проводит поиск p, возвращает ссылку на целое значение из найденной пары,создает новую пару, если p не найдено*/{register pair* pp;for (pp=&vec[free-1]; vec<=pp; pp-- )if (strcmp(p,pp->name) == 0) return pp->val;if (free == max) {//переполнение: вектор увеличиваетсяpair* nvec = new pair[max*2];for (int i=0; i<max; i++) nvec[i] = vec[i];delete vec;vec = nvec;max = 2*max;}pp = &vec[free++];pp->name = new char[strlen(p)+1];strcpy(pp->name,p);pp->val = 0;// начальное значение = 0return pp->val;}Поскольку представление объекта assoc скрыто от пользователя, нужно иметь возможность напечататьего каким-то образом.

В следующем разделе будет показано как определить настоящий итератор длятакого объекта. Здесь же мы ограничимся простой функцией печати:void assoc::print_all(){for (int i = 0; i<free; i++)cout << vec[i].name << ": " << vec[i].val << '\n';}Наконец, можно написать тривиальную программу:main()// подсчет числа вхождений во входной// поток каждого слова{const MAX = 256; // больше длины самого длинного словаchar buf[MAX];assoc vec(512);while (cin>>buf) vec[buf]++;vec.print_all();}Опытные программисты могут заметить, что второй комментарий можно легко опровергнуть.

Решитьвозникающую здесь проблему предлагается в упражнении $$7.14 [20]. Дальнейшее развитие понятиеассоциативного массива получит в $$8.8.Функция operator[]() должна быть членом класса. Отсюда следует, что эквивалентность x[y] == y[x]может не выполняться, если x объект класса. Обычные отношения эквивалентности, справедливые дляопераций со встроенными типами, могут не выполняться для пользовательских типов ($$7.2.2, см.также $$7.9).193Бьерн Страуструп.Язык программирования С++7.8 Вызов функцииВызов функции, т.е.

Характеристики

Список файлов книги

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6367
Авторов
на СтудИзбе
309
Средний доход
с одного платного файла
Обучение Подробнее