Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Во время вызова функции с параметрами не ссылочного типа осуществляется инициализация копией (см. раздел 6.2.1). Точно так же, когда у функции не ссылочный тип возвращаемого значения, возвращаемое значение используется в точке вызова для инициализации копией результата оператора вызова (см. раздел 6.3.2).
Тот факт, что конструктор копий используется для инициализации не ссылочных параметров типа класса, объясняет, почему собственный параметр конструктора копий должен быть ссылкой. Если бы этот параметр не был ссылкой, то вызов не был бы успешным — при вызове конструктора копий должен быть использован конструктор копий для копирования аргумента, но для копирования аргумента следует вызвать конструктор копий и так далее до бесконечности.
Как уже упоминалось, используется ли инициализация копией или прямая инициализация, если используется инициализатор, то потребуется преобразование в явный конструктор (см. раздел 7.5.4):
vector v1(10); // ok: прямая инициализация
vector v2 = 10; // ошибка: конструктор, получающий размер,
// является явным
void f(vector); // параметр f() инициализируется копией
f(10); // ошибка: нельзя использовать явный конструктор для
// копирования аргумента
f(vector(10)); // ok: непосредственно создать временный вектор
// из int
Прямая инициализация вектора v1корректна, но на первый взгляд эквивалентная инициализация копией вектора v2ошибочна, поскольку конструктор вектора, получающий один параметр размера, является явным. По тем же причинам недопустима инициализация копией вектора v2— нельзя неявно использовать явный конструктор при передаче аргумента или возвращении значения из функции. Если нужно использовать явный конструктор, то сделать это следует явно, как в последней строке примера, приведенного выше.
Во время инициализации копией компилятору можно (но не обязательно) пропустить конструктор копий или перемещения и создать объект непосредственно. Таким образом, код
string null_book = "9-999-99999-9"; // инициализация копией
компилятор может выполнить так:
string null_book("9-999-99999-9"); // компилятор пропускает конструктор
// копий
Но даже если компилятор обойдет вызов конструктора копий или перемещения, то он все равно должен существовать и быть доступен (не должен быть закрытым, например) в этой точке программы.
Упражнение 13.1. Что такое конструктор копий? Когда он используется?
Упражнение 13.2. Объясните, почему следующее объявление недопустимо:
Sales_data::Sales_data(Sales_data rhs);
Упражнение 13.3. Объясните, что происходит при копировании объектов классов StrBlobи StrBlobPtr?
Упражнение 13.4. Предположим, класс Pointимеет открытый конструктор копий. Укажите каждый случай использования конструктора копий в этом фрагменте кода:
Point global;
Point foo_bar(Point arg) {
Point local = arg, *heap = new Point(global);
*heap = local;
Point pa[4] = { local, *heap };
return *heap;
}
Упражнение 13.5. Напишите с учетом следующего эскиза класса конструктор копий, копирующий все переменные-члены. Конструктор должен динамически резервировать новую строку (см. раздел 12.1.2) и копировать объект, на который указывает ps, а не сам указатель ps.
class HasPtr {
public:
HasPtr(const std::string &s = std::string()) :
ps(new std::string(s)), i(0) { }
private:
std::string *ps;
int i;
};
13.1.2. Оператор присвоения копии
Подобно тому, как класс контролирует инициализацию своих объектов, он контролирует также присваивание своих объектов:
Sales_data trans, accum;
trans = accum; // использует оператор присвоения копии
// класса Sales_data
Компилятор сам синтезирует оператор присвоения копии, если он не определен в классе явно.
Прежде чем перейти к синтезируемому оператору присвоения, необходимо ознакомиться с перегрузкой операторов (overloaded operator), подробно рассматриваемой в главе 14.
Перегруженные операторы — это функции, имена которых состоят из слова operatorи символа определяемого оператора. Следовательно, оператор присвоения — это функция operator=. Подобно любой другой функции, у функции оператора есть тип возвращаемого значения и список параметров.
Параметрами перегруженного оператора являются его операнды. Некоторые операторы, например присвоение, должны быть определены, как функции-члены. Когда оператор является функцией-членом, левый операнд связан с неявным параметром this(см. раздел 7.1.2). Правый операнд бинарного оператора, такого как присвоение, передается как явный параметр. Оператор присвоения копии получает аргумент того же типа, что и класс:
class Foo {
public:
Foo& operator=(const Foo&); // оператор присвоения
// ...
};
Для совместимости с оператором присвоения встроенных типов (см. раздел 4.4) операторы присвоения обычно возвращают ссылку на свой левый операнд. Следует также заметить, что библиотека обычно требует от типов, хранимых в контейнере, наличия операторов присвоения, возвращающих ссылку на левый операнд.
Операторы присвоения обычно должны возвращать ссылку на свой левый операнд.
Подобно конструктору копий, компилятор создает синтезируемый оператор присвоения копии (synthesized assignment operator) для класса, если в нем не определен собственный. Аналогично конструктору копий, у некоторых классов синтезируемый оператор присвоения копии не подразумевает присвоения (раздел 13.1.6). В противном случае он присваивает значение каждой нестатической переменной-члена правого объекта соответствующей переменной-члену левого объекта с использованием оператора присвоения копии типа этой переменной. Массивы присваиваются поэлементно. Синтезируемый оператор присвоения копии возвращает ссылку на свой левый операнд.
Например, следующий код эквивалентен синтезируемому оператору присвоения копии класса Sales_data:
// эквивалент синтезируемого оператора присвоения копии
Sales_data&
Sales_data::operator=(const Sales_data &rhs) {
bookNo = rhs.bookNo; // вызов string::operator=
Интервал:
Закладка: