
- •1. Указатели, ссылки, квалификатор const.
- •2. Контейнерные типы данных (vector, list, map, set).
- •3. Итераторы.
- •4. Прототип функции. Параметры функции (указатели, ссылки, массивы, по
- •5. Области видимости и пространства имен.
- •6. Перегрузка функций. Разрешение перегрузки.
- •7. Шаблоны функций, конкретизация.
- •8. Обработка исключений. За и против.
- •9. Обобщенные алгоритмы.
- •10. Классы: инкапсуляция данных, уровни доступа к членам, неявный указатель
- •11. Создание и уничтожение объектов класса. Статические члены класса. Открытые и закрытые конструкторы.
- •12. Перегруженные операторы и преобразования, определенные пользователем.
- •13. Шаблоны классов.
- •14. Открытое и закрытое наследование.
- •15. Полиморфизм.
1. Указатели, ссылки, квалификатор const.
Указатель – это объект, содержащий адрес другого объекта и позволяющий косвенно манипулировать этим объектом. Обычно указатели используются для работы с динамически созданными объектами, для построения связанных структур данных, таких, как связанные списки и иерархические деревья, и для передачи в функции больших объектов – массивов и объектов классов – в качестве параметров.
Указателю не может быть присвоена величина, не являющаяся адресом. Нельзя присвоить указателю одного типа значение, являющееся адресом объекта другого типа. Для разрешения таких ситуаций введен специальный указатель void, который может указывать на любой тип данных.
Для того чтобы обратиться к объекту, имея его адрес, нужно применить операцию разыменования (*). К указателю можно прибавлять целое значение, можно также вычитать из него. Указатель базовго класса может указывать на потомков.
Ссылочный тип, иногда называемый псевдонимом, служит для задания объекту дополнительного имени. Ссылка позволяет косвенно манипулировать объектом, точно так же, как это делается с помощью указателя. Однако эта косвенная манипуляция не требует специального синтаксиса, необходимого для указателей. Обычно ссылки употребляются как формальные параметры функций.
Ссылочный тип обозначается указанием оператора взятия адреса (&) перед именем переменной. Ссылка должна быть инициализирована. похожа на указатель, она должна быть инициализирована не адресом объекта, а его значением.
квалификатор const - превращаем переменную в константу со значением, значение которой не может быть изменено. константы без ее инициализации также вызывает ошибку компиляции. компилятор просто запрещает присваивание адресов констант обычным указателям. решение - указатели, объявленные со спецификатором const. Константный указатель не позволяет изменять адресуемый им объект с помощью косвенной адресации. В реальных программах указатели на константы чаще всего употребляются как формальные параметры функций. Попытка присвоить значение константному указателю вызовет ошибку компиляции.
int funct (int, int) const {}.
2. Контейнерные типы данных (vector, list, map, set).
Контейнеры служат для хранения данных. Последовательный контейнер содержит упорядоченный набор элементов одного типа. Можно выделить два основных типа контейнеров – вектор (vector) и список (list). Третий последовательный контейнер – двусторонняя очередь (deque) – обеспечивает ту же функциональность, что и vector, но особенно эффективно реализует операции вставки и удаления первого элемента. deque следует применять, например, при реализации очереди, из которой извлекается только первый элемент. Все сказанное ниже относительно вектора применимо также и к deque. Трудоемкость O n.
Вектор представляет собой область памяти, где элементы хранятся друг за другом. Для этого типа произвольный доступ можно реализовать очень эффективно, поскольку каждый из них находится на некотором фиксированном расстоянии от начала. Однако вставка, кроме случая добавления в конец, крайне неэффективна: операция вставки в середину вектора потребует перемещения всего, что следует за вставляемым. Особенно это сказывается на больших векторах. (Класс deque устроен аналогично, однако операции вставки и удаления самого первого элемента работают в нем быстрее; это достигается двухуровневым представлением контейнера, при котором один уровень представляет собой реальное размещение элементов, а второй уровень адресует первый и последний из них.).
Список располагается в памяти произвольным образом. Каждый элемент содержит указатели на предыдущий и следующий, что позволяет перемещаться по списку вперед и назад. Вставка и удаление реализованы эффективно: изменяются только указатели. С другой стороны, произвольный доступ поддерживается плохо: чтобы прийти к определенному элементу, придется посетить все предшествующие. Кроме того, в отличие от вектора, дополнительно расходуется память под два указателя на каждый элемент списка.
Вектор может расти динамически. Он должен выделить область памяти, достаточную для хранения всех элементов, скопировать в эту область все старые элементы и освободить ту память, в которой они содержались раньше. Если при этом элементы вектора являются объектами класса, то для каждого из них при таком копировании вызываются конструктор и деструктор. Поскольку у списка нет необходимости в таких дополнительных действиях при добавлении новых элементов, кажется очевидным, что ему проще поддерживать динамический рост контейнера. Вектор может запрашивать память не под каждый новый элемент. Вместо этого она запрашивается с некоторым запасом, так что после очередного выделения вектор может поместить в себя некоторое количество элементов, не обращаясь за ней снова. Емкость – это максимальное количество элементов, которое может вместить контейнер без дополнительного выделения памяти. Размер – это реальное количество элементов, хранящихся в данный момент в контейнере. Размер можно получить с помощью функции size().
вектор лучше подходит для типов данных малого размера, нежели список, и наоборот. Эта разница объясняется необходимостью выделения памяти и копирования в нее старых элементов. Однако размер данных – не единственный фактор, влияющий на эффективность. Сложность типа данных также ухудшает результат. Вставка элемента как в список, так и в вектор, требует вызова копирующего конструктора, если он определен. (Копирующий конструктор инициализирует один объект значением другого. Объекты простого класса вставляются побитовым копированием, а для строк и сложных классов это производится вызовом копирующего конструктора.
int main() {
vector< string > svec;
svec.reserve( 32 ); // задает емкость равной 32
// ...
}
Ассоциативный контейнер эффективно реализует операции проверки существования и извлечения элемента. Два основных ассоциативных контейнера – это отображение (map) и множество (set). map состоит из пар ключ/значение, причем ключ используется для поиска элемента, а значение содержит хранимую информацию. Телефонный справочник хорошо иллюстрирует понятие отображения: ключом является фамилия и имя абонента, а значением – его телефонный номер. Элемент контейнера set содержит только ключ, поэтому set эффективно реализует операцию проверки его существования. В контейнерах map и set не может быть дубликатов – повторяющихся ключей. Для поддержки дубликатов существуют контейнеры multimap и multiset. Трудоемкость O log n.
В map хранятся пары ключ/значение.
map<string,int> word_count;