План лекции
  • Отступление о цилочисленных типах
    • Что написано в стандарте про размер int, short и long
    • Размер char*
    • Язык программирования: собственно язык и стандартная библиотека, сравнение разных языков
    • Ключевое слово typedef
    • Типы, определенные в стандартных хедерах: ptrdiff_t, size_t
    • Где используется ptrdiff_t
    • Где используется size_t: пример с malloc
  • Классы и объекты
    • Недостатки нашего типа Array
      • Создание копии
      • Копирование
      • Разница между этими 2 понятиями
    • Решение проблем
      • Конструктор копирования
        • Конструктор копирования, создающийся автоматически
        • Запрет вызова конструктора копирования
        • Вызов конструктора копирования и деструктора при передаче параметра
      • Оператор присваивания
        • Возможность запрета опреатора присваивания
        • Почти такой же, как конструктор копирования
        • Проблема с присваиванием самому себе, this
        • Возвращаемый тип


Классы и объекты

Отступление о целочисленных типах

Типы и их размеры

Рассмотрим некоторые целочисленные типы в языке С:

Тип Размер
char 1 байт
int "естественный"
short sizeof(short) <= sizeof(int)
long sizeof(long) >= sizeof(int)
char* "естественный"

Для типов int и char* в графе Размер указано "естественный", но это не значит, что у этих типов всегда одинаковый размер. К int относятся целые числа, обычно соответствующие естественному размеру целых в используемой машине. Размер указателя зависит от того, сколько ячеек памяти мы можем адресовать. К примеру, на 32-битной архитектуре мы умеем адресовывать 232 ячеек памяти, на 64-битной - 264. При этом, на машине с 64-битной архитектурой переменная типа int занимает 32 бита, а char* - 64 бита.

Дополнительные целочисленные типы

Когда мы обсуждаем какой-либо язык программирования, мы обсуждаем две вещи:

Если взять старые языки, например, Pascal, то в его стандартной библиотеке мы найдём довольно мало функций. Со временем, размеры синтаксиса увеличивались не так сильно, в отличие от стандартной библиотеки. Стандартная библиотека языка С составляет пару десятков заголовочных файлов, а в языке Java она насчитывает уже несколько тысяч файлов.

Одним из ключевых слов языка С является typedef. С его помощью мы можем писать свои собственные типы. Например, если мы привыкли к языку Pascal и хотим писать привычное нам integer, а не int, то мы можем создать новый тип:

typedef int integer;

Помимо функций, в стандартной библиотеке определены и некоторые типы, например:

Классы и объекты

Недостатки нашего типа Array

Допустим, мы создали массив и теперь хотим создать ещё один такой же массив:

{
   Array a(25);
   Array b = a;
   ...
}

Когда мы инициализировали массив b таким способом, его поле mySize стало равным 25, а myData стало указывать на ту же часть памяти, что и a.myData. Если сначала был вызван конструктор для массива a, а потом для b, то деструкторы будут вызваны в обратном порядке. Проблема заключается в том, что деструктор b освободит память, а деструктор a будет пытаться освободить память, которую уже освободили.

Ещё с одной проблемой мы можем столкнуться, когда попытаемся скопировать массив в уже существующий:

{
   Array a(25);
   Array c(36);
   c = a;
   ...
}

В этом случае произойдёт утечка памяти, поскольку мы изменим указатель c.myData.

Решение проблем