Poco
Набор open-sorce библиотек для создания кроссплатформенных сетевых и веб-приложений на C++, хорош тем, что множество типовых задач в библиотеке уже решены, что уменьшает время разработки и ошибки, плюс реализована удобная работа с базами данныхSQL, MonoDB и Redis.
https://pocoproject.org
Набор open-sorce библиотек для создания кроссплатформенных сетевых и веб-приложений на C++, хорош тем, что множество типовых задач в библиотеке уже решены, что уменьшает время разработки и ошибки, плюс реализована удобная работа с базами данныхSQL, MonoDB и Redis.
https://pocoproject.org
Что такое stack overflow?
stack overflow (переполнение стека) — это программная ошибка, которая возникает, когда программа пытается использовать больше памяти на стеке, чем доступно. Стэк — это область памяти, используемая для хранения локальной информации функций, таких как параметры, локальные переменные и возвращаемые значения.
Когда функция вызывается, ее адрес возврата сохраняется на стеке. Затем, когда функция завершается, ее адрес возврата восстанавливается из стека, и управление передается следующей функции в стеке вызовов.
Когда происходит переполнение стека, программа аварийно завершается. Это может привести к потере данных или даже к повреждению системы.
stack overflow (переполнение стека) — это программная ошибка, которая возникает, когда программа пытается использовать больше памяти на стеке, чем доступно. Стэк — это область памяти, используемая для хранения локальной информации функций, таких как параметры, локальные переменные и возвращаемые значения.
Когда функция вызывается, ее адрес возврата сохраняется на стеке. Затем, когда функция завершается, ее адрес возврата восстанавливается из стека, и управление передается следующей функции в стеке вызовов.
Когда происходит переполнение стека, программа аварийно завершается. Это может привести к потере данных или даже к повреждению системы.
#вопросы_с_собеседований
Напишите программу на C++, которая запрашивает у пользователя два числа и выполняет одну из простых математических операций: сложение, вычитание, умножение или деление. Пользователь должен вводить операцию в виде символа (+, -, *, /).
Подсказка: Используйте конструкцию switch для выполнения различных операций.
Решение:
1. Переменные: Определить переменные для чисел и операции.
2. Ввод данных: Запросить у пользователя два числа и символ операции.
3. Выбор операции: Использовать switch для определения типа операции.
4. Выполнение операции: Выполнить выбранную операцию, учитывая возможные ошибки (деление на ноль).
5. Вывод результата: Вывести результат операции.
6. Обработка ошибок: В случае ошибки вывести сообщение и завершить программу.
7. Возвращение значения: Вернуть 0 при успешном завершении, ненулевой код при ошибке.
Напишите программу на C++, которая запрашивает у пользователя два числа и выполняет одну из простых математических операций: сложение, вычитание, умножение или деление. Пользователь должен вводить операцию в виде символа (+, -, *, /).
Подсказка: Используйте конструкцию switch для выполнения различных операций.
Решение:
2. Ввод данных: Запросить у пользователя два числа и символ операции.
3. Выбор операции: Использовать switch для определения типа операции.
4. Выполнение операции: Выполнить выбранную операцию, учитывая возможные ошибки (деление на ноль).
5. Вывод результата: Вывести результат операции.
6. Обработка ошибок: В случае ошибки вывести сообщение и завершить программу.
7. Возвращение значения: Вернуть 0 при успешном завершении, ненулевой код при ошибке.
Объясните разницу между глубоким и поверхностным копированием и приведите пример, когда каждый тип копирования может быть предпочтительнее.
Глубокое копирование создаёт новый объект, копируя все поля источника и рекурсивно создавая копии всех объектов, на которые эти поля ссылаются. Таким образом, все ссылки в копии ведут на отдельные объекты, не связанные с оригиналом. Поверхностное копирование создаёт новый объект, но копирует только значения полей на верхнем уровне. Если поля являются ссылками на другие объекты, то копия будет ссылаться на те же объекты, что и исходный.
Глубокое копирование предпочтительно, когда нужно полностью изолировать копию от оригинала, чтобы изменения в одном не влияли на другой. Поверхностное копирование эффективно, когда нужно сэкономить память или время на копирование, и если объекты, на которые есть ссылки, не изменяются или их изменения допустимы в обоих экземплярах.
#вопросы_с_собеседований
Глубокое копирование предпочтительно, когда нужно полностью изолировать копию от оригинала, чтобы изменения в одном не влияли на другой. Поверхностное копирование эффективно, когда нужно сэкономить память или время на копирование, и если объекты, на которые есть ссылки, не изменяются или их изменения допустимы в обоих экземплярах.
#вопросы_с_собеседований
#вопросы_с_собеседований
Может ли inline-функция быть рекурсивной в С++?
Да, inline-функция может быть рекурсивной в С++. Однако, компилятор может отказаться от встраивания рекурсивной функции, если это приведет к чрезмерному расходу памяти или времени.
Чтобы заставить компилятор встроить рекурсивную функцию, можно использовать директиву препроцессора
На картинке выше функция вычисляет факториал числа. При компиляции этой функции с помощью компилятора GCC с опцией -O2 будет получен следующий результат:
Это означает, что функция
Однако, если компилятор считает, что встраивание рекурсивной функции приведет к чрезмерному расходу памяти или времени, он может отказаться от этого. Например, если функция
Может ли inline-функция быть рекурсивной в С++?
Да, inline-функция может быть рекурсивной в С++. Однако, компилятор может отказаться от встраивания рекурсивной функции, если это приведет к чрезмерному расходу памяти или времени.
Чтобы заставить компилятор встроить рекурсивную функцию, можно использовать директиву препроцессора
#pragma inline_recursion(on)
.На картинке выше функция вычисляет факториал числа. При компиляции этой функции с помощью компилятора GCC с опцией -O2 будет получен следующий результат:
factorial(int) at factorial.cc:5
Это означает, что функция
factorial
будет встроена в код.Однако, если компилятор считает, что встраивание рекурсивной функции приведет к чрезмерному расходу памяти или времени, он может отказаться от этого. Например, если функция
factorial
вызывается очень часто, компилятор может решить, что встраивание функции приведет к избыточному дублированию кода. В этом случае компилятор будет использовать обычный вызов функции.Shared memory
Shared memory является мощным инструментом для межпроцессного взаимодействия, позволяя нескольким процессам совместно использовать область памяти. Это может быть полезно для:
— Повышения производительности: Обмен данными через shared memory гораздо быстрее, чем традиционные методы, такие как межсетевое взаимодействие или файлы.
— Уменьшения задержки: Данные доступны обоим процессам напрямую в памяти, устраняя необходимость копирования.
— Упрощения синхронизации: Совместное использование памяти упрощает реализацию синхронизации между процессами.
Однако использование shared memory также имеет свои сложности:
— Потенциальные ошибки синхронизации: Необходимо тщательно продумать механизмы синхронизации, чтобы избежать проблем.
— Отсутствие защиты памяти: Доступ к shared memory могут получить и другие процессы, если не реализованы механизмы защиты.
— Сложность отладки: Отладка программ, использующих shared memory, может быть более сложной, чем отладка традиционных программ.
#для_начинающих
Shared memory является мощным инструментом для межпроцессного взаимодействия, позволяя нескольким процессам совместно использовать область памяти. Это может быть полезно для:
— Повышения производительности: Обмен данными через shared memory гораздо быстрее, чем традиционные методы, такие как межсетевое взаимодействие или файлы.
— Уменьшения задержки: Данные доступны обоим процессам напрямую в памяти, устраняя необходимость копирования.
— Упрощения синхронизации: Совместное использование памяти упрощает реализацию синхронизации между процессами.
Однако использование shared memory также имеет свои сложности:
— Потенциальные ошибки синхронизации: Необходимо тщательно продумать механизмы синхронизации, чтобы избежать проблем.
— Отсутствие защиты памяти: Доступ к shared memory могут получить и другие процессы, если не реализованы механизмы защиты.
— Сложность отладки: Отладка программ, использующих shared memory, может быть более сложной, чем отладка традиционных программ.
#для_начинающих
ext_aggregate
Функция
Первый аргумент — это контейнер, над элементами которого необходимо вычислить агрегатную функцию.
Второй аргумент — это функция, которая определяет агрегатную функцию, которую необходимо вычислить.
Функция
#для_продвинутых
ext_aggregate
— это функция, которая используется для вычисления агрегатных функций над элементами контейнера. Агрегатные функции — это функции, которые возвращают значение, основанное на значениях всех элементов контейнера. Например, функция sum()
возвращает сумму всех элементов контейнера, а функция max()
возвращает максимальное значение в контейнере.Функция
ext_aggregate
принимает два аргумента:Первый аргумент — это контейнер, над элементами которого необходимо вычислить агрегатную функцию.
Второй аргумент — это функция, которая определяет агрегатную функцию, которую необходимо вычислить.
Функция
ext_aggregate
возвращает значение, вычисленное агрегатной функцией.#для_продвинутых
execution policy
Execution policy реализован в виде перечисления
#для_продвинутых
execution policy
— это механизм, который позволяет указать, как будет выполняться блок кода. Он предоставляет разработчикам возможность контролировать, будет ли код выполняться на одном потоке, на нескольких потоках, или на нескольких ядрах процессора.Execution policy реализован в виде перечисления
std::execution_policy
. Оно содержит следующие значения:std::execution::seq
— блок кода будет выполняться последовательно, на одном потоке.std::execution::par
— блок кода будет выполняться параллельно, на нескольких потоках.std::execution::par_unseq
— блок кода будет выполняться параллельно, но не обязательно последовательно.std::execution::par_for
— блок кода будет выполняться параллельно, используя цикл for
.std::execution::par_for_each
— блок кода будет выполняться параллельно, используя цикл for each
.#для_продвинутых
std::format
Форматирование текста с помощью
Чтобы использовать
#для_начинающих
std::format
— это функция в C++, которая используется для форматирования текста. Она может использоваться для вставки значений переменных, строк и других объектов в шаблон текста.Форматирование текста с помощью
std::format
похоже на форматирование текста с помощью printf
. Однако std::format
более безопасный и эффективный, чем printf
.Чтобы использовать
std::format
, вам необходимо включить заголовочный файл <format>
.#для_начинающих
Forward_list
#для_продвинутых
Forward_list
в C++ - это контейнер, поддерживающий быструю вставку и удаление элементов из любого места в контейнере. Быстрый доступ к случайным элементам не поддерживается. Реализуется как односвязный список. По сравнению с std::list
этот контейнер обеспечивает более эффективное хранение памяти, когда двунаправленная итерация не требуется.Forward_list
соответствует требованиям Container
(за исключением члена функции size
и того, что сложность оператора ==
всегда линейна), AllocatorAwareContainer
и SequenceContainer
.#для_продвинутых
Флаг компиляции -fPIC
Флаг компиляции
Код с независимой позицией необходим для создания динамических библиотек, которые могут быть загружены в память в любое место. Это также полезно для создания разделяемых модулей, которые могут быть подключены к другим программам.
Чтобы использовать флаг
Это создаст исполняемый файл main, который может быть связан с другими библиотеками.
#для_продвинутых
Флаг компиляции
-fPIC
в С++ означает «Position Independent Code» (код с независимой позицией). Этот флаг заставляет компилятор создавать код, который может быть связан с другими библиотеками, независимо от того, где они расположены в памяти.Код с независимой позицией необходим для создания динамических библиотек, которые могут быть загружены в память в любое место. Это также полезно для создания разделяемых модулей, которые могут быть подключены к другим программам.
Чтобы использовать флаг
-fPIC
, необходимо добавить его в командную строку компилятора. Например, для компиляции файла main.cpp
с использованием флага -fPIC
можно использовать следующую команду:g++ -fPIC main.cpp -o main
Это создаст исполняемый файл main, который может быть связан с другими библиотеками.
#для_продвинутых
Что такое PIMPL?
PIMPL (Pointer to Implementation) — это идиома проектирования в C++, которая используется для управления инкапсуляцией деталей реализации класса и сокрытия их от пользователей класса. Она также известна как «Cheshire Cat» (улыбка Чеширского кота) из-за того, что она позволяет «убрать» детали реализации из интерфейса класса, оставив только указатель на них.
Идея PIMPL заключается в том, чтобы внести все детали реализации класса в отдельную структуру или класс, а затем хранить указатель на эту структуру в основном классе. Таким образом, пользователи класса видят только публичный интерфейс основного класса, а детали реализации остаются скрытыми.
#для_продвинутых
PIMPL (Pointer to Implementation) — это идиома проектирования в C++, которая используется для управления инкапсуляцией деталей реализации класса и сокрытия их от пользователей класса. Она также известна как «Cheshire Cat» (улыбка Чеширского кота) из-за того, что она позволяет «убрать» детали реализации из интерфейса класса, оставив только указатель на них.
Идея PIMPL заключается в том, чтобы внести все детали реализации класса в отдельную структуру или класс, а затем хранить указатель на эту структуру в основном классе. Таким образом, пользователи класса видят только публичный интерфейс основного класса, а детали реализации остаются скрытыми.
#для_продвинутых
Requires-expression
Вот основные особенности requires-expression:
— Логическое выражение: Оценивается в
— Используется для проверки:
— Соответствия типам и выражениям концепциям.
— Других требований к типам и выражениям.
Применение:
— Внутри шаблонов.
— Внутри
— Вне шаблонов и
Преимущества использования requires-expression:
— Улучшение читаемости и понятности кода: Требования к типам и выражениям становятся более явными.
— Повышение безопасности кода: Ошибки, связанные с несоответствием типов, выявляются во время компиляции.
— Улучшение производительности: Константные проверки требований позволяют оптимизировать код.
#для_продвинутых
Requires-expression
(выражение требований) – это мощная функциональность, появившаяся в C++20, которая позволяет выражать требования к типам и выражениям непосредственно в коде.Вот основные особенности requires-expression:
— Логическое выражение: Оценивается в
true
или false
во время компиляции.— Используется для проверки:
— Соответствия типам и выражениям концепциям.
— Других требований к типам и выражениям.
Применение:
— Внутри шаблонов.
— Внутри
constexpr
функций.— Вне шаблонов и
constexpr
функций (с ограничениями).Преимущества использования requires-expression:
— Улучшение читаемости и понятности кода: Требования к типам и выражениям становятся более явными.
— Повышение безопасности кода: Ошибки, связанные с несоответствием типов, выявляются во время компиляции.
— Улучшение производительности: Константные проверки требований позволяют оптимизировать код.
#для_продвинутых
std::unordered_set
Доступ к элементам
#для_начинающих
std::unordered_set
— это ассоциативный контейнер, который содержит множество уникальных объектов типа Key
. Это позволяет быстро получить доступ к отдельным элементам, поскольку после вычисления хэша он указывает на точный бакет, в который помещен элемент.std::unordered_set
использует хэширование для хранения элементов. Это означает, что каждый элемент контейнера преобразуется в целое число, называемое хеш-значением. Хеш-значения элементов используются для размещения их в бакетах, которые представляют собой массивы элементов.Доступ к элементам
std::unordered_set
осуществляется с помощью их хеш-значений. Это позволяет получить доступ к элементу за время O(1), что быстрее, чем у других ассоциативных контейнеров, таких как std::map
и std::multimap
.#для_начинающих
Почленное копирование
Почленное (посточленное) копирование в C++ означает копирование значений одного объекта в другой объект с сохранением их структуры. Это может быть полезно, например, при копировании элементов массива, элементов контейнера (например, вектора), или при копировании полей одного объекта в другой.
В C++ для почленного копирования часто используются конструкторы копирования, операторы присваивания и инициализация с помощью списков инициализации.
#для_продвинутых
Почленное (посточленное) копирование в C++ означает копирование значений одного объекта в другой объект с сохранением их структуры. Это может быть полезно, например, при копировании элементов массива, элементов контейнера (например, вектора), или при копировании полей одного объекта в другой.
В C++ для почленного копирования часто используются конструкторы копирования, операторы присваивания и инициализация с помощью списков инициализации.
#для_продвинутых
Решето Эратосфена
Решето Эратосфена — это алгоритм для нахождения всех простых чисел в заданном диапазоне.
Этот код определяет функцию
Просто скопируйте этот код в файл с расширением .cpp, скомпилируйте его и выполните. После ввода верхней границы диапазона, программа выведет все простые числа в этом диапазоне.
#для_начинающих
Решето Эратосфена — это алгоритм для нахождения всех простых чисел в заданном диапазоне.
Этот код определяет функцию
sieveOfEratosthenes
, которая находит все простые числа в диапазоне от 2 до n. Он использует булевый вектор isPrime
, чтобы отмечать числа как простые или составные, и затем выводит список простых чисел.Просто скопируйте этот код в файл с расширением .cpp, скомпилируйте его и выполните. После ввода верхней границы диапазона, программа выведет все простые числа в этом диапазоне.
#для_начинающих
std::atomic_flag::wait
Вот общий синтаксис
#для_продвинутых
std::atomic_flag::wait
является частью стандартной библиотеки C++ и используется для ожидания, пока флаг std::atomic_flag
станет равным clear
, и затем устанавливает его в set
. Это может быть полезно для синхронизации между потоками.Вот общий синтаксис
std::atomic_flag::wait
:void wait(bool clear_val = true) const;
clear_val
— это булевое значение, которое указывает, должен ли флаг быть установлен в clear после ожидания (по умолчанию true).#для_продвинутых
Функция map::at()
Функция
Использование
#для_начинающих
Функция
map::at()
в C++ используется для доступа к элементу по указанному ключу в структуре данных std::map
. std::map
— это контейнер, который реализует ассоциативный массив, где каждому ключу соответствует значение. map::at()
предоставляет безопасный способ доступа к элементам std::map
, так как она генерирует исключение в случае отсутствия указанного ключа в отображении.Использование
map::at()
рекомендуется в случаях, когда вы хотите обеспечить безопасный доступ к элементам std::map
и управлять исключениями при отсутствии ключа.#для_начинающих
Алгоритм adjacent_find()
Алгоритм
#для_продвинутых
Алгоритм
adjacent_find()
выполняет поиск совпадающих смежных элементов внутри последовательности, заданной параметрами first
и last
, и возвращает итератор для первого элемента. Если ни одной такой смежной пары не обнаружено, возвращается значение end. Первая версия предназначена для поиска эквивалентных элементов. Вторая же позволяет задать собственный метод определения совпадающих элементов.#для_продвинутых
Алгоритм IOTA
Алгоритм IOTA — это функция, которая заполняет диапазон последовательными значениями начиная с заданного начального значения. Этот алгоритм полезен, когда вам нужно инициализировать контейнер, например, вектор или массив, последовательными числами.
Таким образом, вы можете использовать
#для_начинающих
Алгоритм IOTA — это функция, которая заполняет диапазон последовательными значениями начиная с заданного начального значения. Этот алгоритм полезен, когда вам нужно инициализировать контейнер, например, вектор или массив, последовательными числами.
Таким образом, вы можете использовать
std::iota
для быстрой инициализации контейнеров последовательными значениями.#для_начинающих
Метод difftime()
Метод
#для_начинающих
Метод
difftime()
используется для вычисления разницы между двумя временными точками, представленными в виде объектов time_t
. Она возвращает разницу между двумя временами в секундах в виде числа с плавающей запятой (тип double).#для_начинающих