I Flashcards

1
Q

Оператор sizeof

A
  • sizeof (объект некоторого типа)
  • Оператор, который возвращает число, равное количеству байт, которое бы занимал в памяти объект этого типа
  • Полезен, когда нужно выделить количество памяти, которой бы хватило на n объектов нужного вам типа, вы пишете n * sizeof (объект некоторого типа)
  • Причем в скобках можно написать как объект, так и просто название типа
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Оператор запятая (,)

A
  • Пример: x=5, y=3, z++, 7
  • Оператор вычисляет сначала левую часть, потом вычисляет правую часть.. и возвращает правую часть (в выражении x=(5,3) x=3)
  • В выражении: x=(x=5, y=3, z++, 7) получится: x=7, y=3, z увеличится на 1
  • Это оператор с самым низким приоритетом из всех существующих операторов
  • В выражении f(5,3) запятая это не оператор, а часть синтаксиса… аналогично тому, как в контексте объявлений int x=5; x это не оператор присваивания, а часть синтаксиса (инициализация)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Управляющие конструкции

A

1. if (bool-expression) statement;

  • statement это инструкция
  • если инструкция единичная, то фигурные скобки не нужны
  • если несколько инструкций, то ставятся { }

2. while (bool-expression) statement;

  • bool-expression - любое выражение, которое конвертируется в bool
  • есть альтернативная форма (с пост-условием): do statement; while (bool-expression);

3. for (Выражение инициализации, выполняемое только раз; Условие выхода, проверяемое в начале каждой итерации; Выражение цикла, выполняемое в конце каждой итерации) statement;

  • самая интересная конструкция
  • | это “или”
  • declaration|expression - это инициализатор (выполняется первым)
  • далее если bool-expression истинно, то выполняется statement
  • далее вычисляется expression и потом за ним снова bool-expression (и так по кругу)
  • любую часть в скобках можно пропустить (и даже все)
  • for(;;); statement это вечный цикл

4. switch

  • switch ( <переменная> ) {
  • case значение1:
  • Выполнить если <переменная> == значение1
  • break;
  • case значение2:
  • Выполнить если <переменная> == значение2
  • break;
  • default:
  • выполнить, если ни один вариант не подошел break;
  • }

5. break;

  • выйти из текущего цикла (любого, может быть внутри for, while и тд)
  • из if выходить через break нельзя

6. continue;

перейти к следующей итерации цикла

7. return expression;

8. goto _(метка)_ ; устаревшее, почти не используется

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Виды ошибок и UB

A
  • Ошибка компиляции (compile-time errors) - программа написана так, что компилятор не может преобразовать её в выполняемый код (невозможно создать выполняемый файл).
  • Ошибки компиляции делятся на лексические, синтаксические и семантические.
  • Лексические ошибка - компилятор не может распознать написанную последовательность символов (например, 2b3;).
  • Синтаксическая ошибка - компилятор не может разпарсить некоторую конструкцию (хотя и понимает отдельные части). Написанная инструкция в целом не корректна (слова не согласованы между собой)
  • Семантическая ошибка - например используется переменная, которую забыли объявить. Или выполняется операция над объектом, которая не поддерживает операции над объектами такого типа (пример: “Съешь себя пожалуйста этим столом”).
  • Ошибка выполнения (runtime errors) - выполняемый файл создался, но программа в ходе выполнения сделала что-то такое, что привело её к краху. Её невозможно отследить на этапе компиляции.
  • Undefined behavior (UB) - написано нечто, не прописанное в стандарте C++. Например, int x=2<<40; Компилятор может исполнить это непредсказуемым образом. Другой пример: ++x = x++;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Указатели

A
  • это боль, самое неприятное в языке
  • объявление массива из 100 элементов: int a[100]; при этом массивы более 2-4 млн выдают runtime error!! что делать, если нужен очень большой массив?
  • при этом a[150], a[-5], 150[a] тоже возвращают значения!
  • операционная система изначально выделяет программе некоторую область памяти (stack)
  • Указатель это специальный тип данных, который служит для предоставления адресов в памяти (int *x;); иначе это переменная, которая содержит адрес другой переменной
  • Можно взять указатель и посмотреть, что “под ним лежит” (*x; вернет int)
  • Указатели можно инкрементировать и дикрементировать, вычитать друг из друга
  • a[5] это по сути указатель, эквивалентный *(a+5) - операция разыменования (* - оператор получения значения по адресу)
  • int b; int *y = &b; (дает адрес этого объекта в памяти)… у это указатель (переменная адресного типа)
  • кроме того, возможно выражение следующего типа (сколь угодно глубоко): int **x = &y;
  • типа данных указателя должен соответствовать типу данных на которые он указывает
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Указатели на функции

A
  • объявленная функция хранится в памяти по некоторому адресу

int f(double, char*) //в функциях можно не указывать названия переменных

int (*p) (double, char*) = &f;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Функции с переменным числом аргументов

A

void f(int x, … ) { }

  • главное, чтобы был первый параметр и дальше можно передавать любые типы в любом количестве
  • чтобы обращаться к таким функциям нужно включить соответствующую библиотеку cstdarg
  • в таком виде этим никто не пользуется
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Аргументы по умолчанию

A

void f (int x, char y = ‘a’);

  • эту функцию можно вызвать как функцию с одним аргументом, так и как функцию с двумя
  • то есть можно не указывать второй аргумент, тогда он по умолчанию сделается равным а
  • важно: аргументы по умолчанию должны быть в конец списка (их может быть несколько или все)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Перегрузка (перезагрузка) функций

A
  • это когда есть несколько функций с одинаковым именем, но разным набором аргументов

Пример:

void f (int x);

int f (char x, int y);

char f(double z);

  • это не ошибка компиляции, в зависимости от того, с какими параметрами будет вызываться f, будет вызываться наиболее подходящая функция
  • если вызвать f от типа, не указанного в описаниях (например, char), то включаются правила разрешения перегрузки (overloading resolution rules)
  • когда у вас есть несколько инструкций, и одна из них более специализированная, чем другие, то будет выбрана именно она

Пример:

void f (int x, int y)

void f (int x, …)

при вызове f (1,2) будет выбрана первая функция

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Операторы new и delete

A
  • как сделать так, чтобы та информация, которая была объявлена внутри функции, не пропала после ее исполнения?
  • у ОС есть память (оперативная) и её может не хватить, и нужно будет попросить ОС выделить дополнительную память - для этого есть оператор new

new type; // возвращается указатель на эту переменную (адрес)

int *p = new int ( ____ ); // эта переменная будет существовать даже после исполнения функции

  • чтобы ОС уничтожила эту переменную, имеется оператор delete

delete p;

  • если вызвать delete от указателя, который ранее не был выдан через new, то будет crash
  • если не использовать delete, то эта информация так и останется в памяти - так можно сожрать всю оперативную память - поэтому всё лишнее нужно удалять
  • поэтому с этими операторами очень больно работать - всегда нужно помнить, что и где выделяется, чтобы это своевременно стирать
  • как вызвать массив?

Пример:

int *p = new int [100];

delete[] p; // для уничтожения массива обязательно нужны []

Еще пример:

int *p = new int [100];

int *pp = new int [10];

delete[] p, pp; //в данном примере массив pp не уничтожится, так как оператор запятая имеет самый низкий приоритет действия

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Ссылки (references)

A
  • как написать функцию, которая меняет свои аргументы? (swap)
  • был ли Ленинград столицей Российской Империи? (в C++ это не так)
  • ссылка это по сути другое название для объекта

Пример 1:

type x;

type &y=x; // это ссылка на x, без & создался бы новый объект y (а не ссылка на старый)

  • теперь y жестко привязан к x и всё, что вы делаете с одной переменной, делается с другой

Пример 2:

void swap (int &x, int &y) {

int t = x;

x=y;

y=t;

}

Пример 3 :

int &f (int x) { // это пример UB - компилятор будет работать некорректно

int y = x + 1

return y;

}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Константы

A
  • нельзя написать int &x=5 так как 5 это константа

const int x = 3; // данный префикс означает, что x не должен меняться (запрещены модифицирующие операции)

const int &t = y; // t и y будут один и тот же объект, при этом t будет считаться константой, а y не константой… к у можно применять модифицирующие операции, а к t нельзя… и при изменении y будет изменяться t, потому что это один и тот же объект

const int *p = ….; // указатель на константу - он сам не является константой и его можно модифицировать, а то, что под ним лежит, нельзя

  • Общее правило: если у вас есть ссылка или указатель на не константу, то вы с её помощью можете проинициализировать ссылку или указатель на константу (в обратную сторону нельзя)
  • Константы и ссылки обязательно нужно инициализировать! (int &x; или const int y; выдаст ошибку компиляции)

const int *p = new int [10]; //такая запись допустима, мы не сможем менять ВСЕ элементы под p, а сам p сдвигать можно

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Операторы явного преобразования типов

A

Именованный оператор приведения имеет следующую форму:

имя_приведения < тип> ( выражение ) ;

где тип - это результирующий тип преобразования, а выражение - приводи­мое значение. Если тип - ссылка, то результат l-значение. Имя_приведения может быть одним из следующих: static_cast, dynamic_cast, const_cast и reinterpret_cast.

1 способ:

(type) (выражение); // вычисляется выражение, а потом преобразуется в заданный тип - так было в C (c-style cast)

2 способ:

static_cast (выражение);

  • возьми выражение и по правилам преобразования преобразуй в заданный тип; если такое преобразование не известно (например оно не возможно или это пользовательский тип), то ошибка компиляции (оператор работает на этапе компиляции)
  • int i, j ;*
  • double slope = static_cast ( j ) / i ;*

3 способ:

reinterpret_cast < > ( )

  • возьми значение, которое тебе дали, и тебе биты в памяти, которые оно занимает, интерпретируй, как если они кодируют выражение типа type
  • этот способ не всегда работает (есть ограничения)
  • используется для приведения указателей разного типа друг к другу

*(reinterpret_cast (&obj));

4 способ:

  • позволяет преобразовывать константы в неконстанты (единственный из этих операторов)

Пример 1:

int x=5;

const int &y = x;

int &z = const_cast (y);

Пример 2:

f (int&) и f (const int&); //заданы две функции (перегрузка)

f (const_cast (x)); такое выражение вынудит компилятор вызвать “f (const int&);” версию функции

5 способ:

dynamic_cast

Явное преобразование типов это “молоток”: static_cast это наиболее “ласковый” метод, reinterpret_cast это совсем хардкорные преобразование типов (лом)… c-style cast это худший вариант каста, “бульдозер” (сломать всё, лишь бы получилось)

Вывод: нужно стараться использовать касты пореже

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Классы и структуры

A
  • грубо говоря, это пользовательский тип данных

Пример 1:

class C; //объявление класса

Пример 2:

class C {
 // внутри класса находятся поля или методы (по умолчанию они считаются private)

public: // всё, что написано после считается public

}; // после определения класса нужно ставить ; после фигурной скобки!!! (тонкий момент)

Что находится внутри класса:

  • поля - переменные/объекты, которые в классе хранятся
  • методы класса - функции, выполняемые над объектами этого класса

Для того, чтобы разграничить методы и поля, которые видны и не видны внешнему пользователю, используются слова private и public (модификаторы доступа) и этим класс отличается от структуры.

Обычно сначала показывают public часть, потом private (code-style).

Пример 3:

struct s {

// в структуре всё по умолчанию public (наследование по умолчанию тоже публичное)

int x;

};

В остальных аспектах классы и структуры это одно и то же

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Конструктор

A
  • особый метод класса, вызываемый 1 раз сразу после создания класса
  • конструктор имеет то же имя, что и имя класса
  • причем конструктор ничего не возвращает (единственная функция в своем роде)
  • конструктор должен быть публичным или возникнет вопрос с созданием экземпляра

Пример 1:

class tStudent{

int age // private

public:

tStudent (int _age) // конструктор

{

age = _age;

}

~tStuden () // деструктор

{

cout << “Пока!”;

}

}; // в конце должна быть ; !!!

Как вызвать конструктор:

tStudent s2(17); // специфический тип инициализации, без “=”

tStudent s3(s2); // конструктор с клонированием

_________________________________________

int main ( ) {

C x; // инструкция по созданию типа создается с помощью конструктора

}

Конструктор (пишется внутри класса)

С ( ….. ) { … }

Пример 2: (класс строк)

class string {

chat* str;

int size;

string (cons char* str_, int size_) {

str = new char [size_];

for (…)

}
};

  • если конструктор не определен, то компилятор генерирует конструктор по умолчанию
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Деструктор

A
  • Функция, которая вызывается, если объект выходит из области видимости (delete)

~ string ( ) {

delete [] str;

};

  • если явно не объявить, тогда компилятор сгеренирует диструктор по умолчанию (но выделенная память НЕ УДАЛИТСЯ)
  • если конструкторов может быть написано много разных, то деструктор всегда без параметров - для одного класса только один
  • диструктор как правило не вызывается, посколько он существует на обособленном объеме памяти
17
Q

Конструктор копирования

A
  • объект инициализируются другим объектом такого же типа
18
Q

команда, чтобы не писать каждый раз std

A

using namespace std;

19
Q

Включить русские символы

A

setlocale(LC_ALL, “Rus”);

20
Q

Escape последовательности

A
  • \b удаление последнего выведенного символа
  • \n переход на новую строку
  • \t табуляция

вставлять внутрь кавычек, в любую часть текста

cout<< “ . . . “

21
Q

Типы данных

A