C++ geek
3.56K subscribers
251 photos
2 videos
16 links
Учим C/C++ на примерах
Download Telegram
Работа с файлами

Для того чтобы прочитать файл понадобится выполнить те же шаги, что и при записи в файл с небольшими изменениями:

1) создать объект класса ifstream и связать его с файлом, из которого будет производиться считывание;
2) прочитать файл;
3) закрыть файл.

➡️ @cpp_geek
vptr (Virtual Pointer)

vptr — это указатель на виртуальную таблицу, которая содержит информацию о виртуальных функциях класса. vptr используется при вызове виртуальных функций, а также при операции приведения типов с помощью dynamic_cast.

В этом примере мы создали два класса: Base и Derived. Класс Derived наследуется от класса Base и переопределяет его виртуальную функцию func(). Затем мы создали объект класса Derived и присвоили его адрес указателю на базовый класс Base.

Затем вызываем функцию func() с помощью указателя на базовый класс. Здесь vptr смотрит на таблицу виртуальных функций, чтобы определить, какую функцию вызывать.

Результатом будет вывод "Derived", так как мы переопределили функцию в классе Derived.

➡️ @cpp_geek
Функция remove_if

Функция remove_if() используется для удаления из списка всех значений, которые соответствуют истине предикату или условию, заданному в качестве параметра функции.

Функция выполняет итерацию по каждому члену контейнера списка и удаляет все элементы, которые возвращают true для предиката.

➡️ @cpp_geek
std::sort

std::sort — это функция стандартной библиотеки для сортировки элементов в контейнерах, таких как вектор или список.
Чтобы использовать std::sort, нужно подключить заголовочный файл .

Метод принимает в качестве аргументов итераторы на начало и конец сортируемой последовательности и сортирует элементы в возрастающем порядке по умолчанию.

Для определения порядка сортировки можно указать свой компаратор.

➡️ @cpp_geek
Что дают разные модификаторы при наследовании?

Ответ:
Изменяют зону видимости членов базового класса.
При private наследовании protected и public члены становятся private. При protected наследовании public становится protected. А при public ничего не изменяется.

➡️ @cpp_geek
Какая разница между статической и динамической библиотеками?

Статическая библиотека — это набор объектных файлов, которые компилятор или компоновщик могут использовать для создания исполняемого файла. Когда вы компилируете программу, которая использует статическую библиотеку, код из библиотеки копируется в исполняемый файл. Это означает, что каждый исполняемый файл содержит свою собственную копию кода из статической библиотеки.

Динамическая библиотека — это набор функций и данных, которые могут быть загружены и использованы несколькими программами одновременно. Когда вы компилируете программу, которая использует динамическую библиотеку, исполняемый файл содержит только ссылки на функции и данные в библиотеке. Код из динамической библиотеки загружается в память только один раз и может быть использован несколькими программами.

Основное отличие между статическими и динамическими библиотеками заключается в том, как они используются и распространяются. Статические библиотеки встраиваются непосредственно в исполняемый файл, что увеличивает его размер, но делает его самодостаточным. Динамические библиотеки распространяются отдельно от исполняемого файла и могут быть использованы несколькими программами, что уменьшает размер каждого исполняемого файла и обеспечивает лучшее использование памяти.

➡️ @cpp_geek
Примеры C++ кода до и после Ranges

Объединяем все строки в данном диапазоне в одно значение.

➡️ @cpp_geek
Перед вами два примера кода для печати вектора. Есть ли преимущества использования одного или другого?

Пример 1:
c++
vector vec;
/* ... .. ... */
for (auto itr = vec.begin(); itr != vec.end(); itr++) {
itr->print();
}


Пример 2:
c++
vector vec;
/* ... .. ... */
for (auto itr = vec.begin(); itr != vec.end(); ++itr) {
itr->print();
}


Хотя оба кода будут генерировать одинаковые выходные данные, пример 2 является более производительным вариантом. Это связано с тем, что оператор после инкремента itr++ обходится дороже, чем оператор перед инкрементом ++itr.

Оператор пост-инкремента генерирует копию элемента, прежде чем приступить к увеличению элемента и возврату копии. Более того, большинство компиляторов автоматически оптимизируют пример 1, неявно преобразуя его в пример 2.

➡️ @cpp_geek
Лямбда-выражения

В C++ 11 появилась поддержка лямбда-выражений. Они напоминают анонимные функции в JavaScript, их можно сравнить с функциональными объектами без имён. Они захватывают переменные в различных областях видимости в зависимости от их описания, для которого используются компактные синтаксические конструкции. Кроме того, их можно назначать переменным.

Лямбда-выражения — весьма полезный инструмент для тех случаев, когда в коде нужно выполнить какую-нибудь небольшую операцию, но для этого не хочется писать отдельную функцию. Ещё один распространённый пример их использования — создание функций, используемых при сравнении значений.

➡️ @cpp_geek
Можно ли использовать ссылку при возвращении из функции? Это хорошо или плохо?

Нельзя:
• никогда нельзя возвращать ссылку на локальную переменную, созданную внутри функции, потому что она разрушится сразу после выхода из функции;
• нельзя возвращать ссылку на выделенную память, потому что её нельзя будет очистить.

Можно:
• когда возвращается константная ссылка на член класса;
• когда Вы пишете оператор <<, оператор = и оператор индексирования, они должны возвращать ссылку на объект.

Возвращать ссылку - это хорошо, потому что не вызывается лишний копирующий конструктор для возвращаемого значения, но, иногда лучше и правильнее возвращать по значению.

➡️ @cpp_geek
Алгоритм lower_bound

Возвращает итератор, указывающий на первую позицию в отсортированной последовательности, ограниченной диапазоном [first, last), в которую можно вставить значение value, не нарушая упорядоченности.

➡️ @cpp_geek
Примеры C++ кода до и после Ranges

Удаляем два наименьших и два самых больших значения диапазона и оставляем остальные, упорядоченные во втором диапазоне.

➡️ @cpp_geek
Алгоритм iota

Присваивает каждому элементу в диапазоне [first,last) последовательные значения val, как если бы они увеличивались ++val после записи каждого элемента.

➡️ @cpp_geek
Примеры C++ кода до и после Ranges

Измените несортированный диапазон, чтобы он сохранял только уникальные значения, но в обратном порядке.

➡️ @cpp_geek
Как сгенерировать pure virtual function call исключение?

Ответ:
Нужно вызвать чисто виртуальный метод в конструкторе родительского класса т.е. до создания дочернего, в котором этот метод реализован. Т.к. современный компилятор не даст это сделать напрямую, то нужно будет использовать промежуточный метод.

➡️ @cpp_geek
Функция map::at()

Map - это контейнер в STL, который используется для хранения элементов в виде пары ключ-значение. Внутренне элементы map всегда сортируются по ее ключу. Карты в основном реализованы в виде бинарных деревьев поиска.

Функция map::at() используется для возврата ссылки на элемент, связанный с ключом k.

➡️ @cpp_geek
Объявление классов и функций

В init части цикла for можно объявлять не одни лишь переменные. Здесь также можно разместить классы и функции.

Благодаря этому можно использовать множество переменных с разными типами.

➡️ @cpp_geek
Алгоритм distance

Возвращает расстояние до желаемой позиции от первого итератора. Эта функция очень полезна при поиске нужного нам индекса.

➡️ @cpp_geek
Сколько раз будут выполняться циклы внутри программы?

Ответ:
Ответ: в первом случае цикл не выполнится никогда, а во втором случае будет выполняться бесконечно.

Объяснение:
В первом цикле условие прекращения цикла имеет тип беззнакового char, значит, у нас присвоение n 256 вызовет переполнение и n станет равным 0. Цикл превратится в for(unsigned char i = 0; i < 0; ++i), а, значит, условие цикла не выполняется, и мы даже не войдём в тело цикла. Во втором цикле другая ситуация, он превращается в for(unsigned char i = 0; i < 256; ++i), и так как i не может быть больше, чем 255, то условие цикла будет выполняться всегда.

➡️ @cpp_geek
Бывает такое, что оператор new не выделяет память?

Ответ:
Да, бывает, когда new передаётся указатель на уже выделенную память (например, с помощью malloc). Это называется placement new. И оператор new без изменения возвращает второй параметр - указатель (void* operator new(std::size_t, void*)). Это используется для создания объектов в выделенном "хранилище" или после malloc.

Важно! В этом случае деструктор нужно вызывать самостоятельно!

➡️ @cpp_geek
Как сравнивают bool, int, float, указатели со значением и с нулем?

Ответ на картинке.

➡️ @cpp_geek