Семантика перемещения
Семантика перемещения позволяет эффективно перемещать ресурсы между объектами без копирования данных. Это понятие стало особенно актуальным в свете улучшений, внесенных в язык C++11 и последующих стандартах.
Семантика перемещения решает проблемы, связанные с копированием больших данных или ресурсов, что может быть очень затратным по времени и памяти. Вместо копирования данные «перемещаются» из одного объекта в другой, при этом исходный объект теряет право владения этими данными. Это осуществляется с использованием специальных методов и операторов, таких как конструктор перемещения (
Семантика перемещения позволяет эффективно перемещать ресурсы между объектами без копирования данных. Это понятие стало особенно актуальным в свете улучшений, внесенных в язык C++11 и последующих стандартах.
Семантика перемещения решает проблемы, связанные с копированием больших данных или ресурсов, что может быть очень затратным по времени и памяти. Вместо копирования данные «перемещаются» из одного объекта в другой, при этом исходный объект теряет право владения этими данными. Это осуществляется с использованием специальных методов и операторов, таких как конструктор перемещения (
move constructor) и оператор перемещения (move assignment operator).Виртуальные функции
Виртуальные функции — это механизм, позволяющий создавать функции в базовом классе, которые могут быть переопределены в производных классах. Основная идея заключается в том, что виртуальные функции могут вызывать методы из объектов производных классов через указатели или ссылки на базовый класс, и при этом будет вызвана та версия функции, которая соответствует реальному типу объекта.
Чтобы объявить функцию виртуальной, необходимо использовать ключевое слово
Виртуальные функции — это механизм, позволяющий создавать функции в базовом классе, которые могут быть переопределены в производных классах. Основная идея заключается в том, что виртуальные функции могут вызывать методы из объектов производных классов через указатели или ссылки на базовый класс, и при этом будет вызвана та версия функции, которая соответствует реальному типу объекта.
Чтобы объявить функцию виртуальной, необходимо использовать ключевое слово
virtual в определении функции в базовом классе. Производные классы могут переопределять виртуальные функции с помощью того же ключевого слова virtual. Таким образом, при вызове виртуальной функции через указатель или ссылку на базовый класс будет вызвана версия функции из реального типа объекта.Перегрузка функций
Перегрузка функций — это возможность определения нескольких функций с одним и тем же именем, но разными параметрами. Когда вызывается такая функция, компилятор определяет, какая из перегруженных функций должна быть вызвана, основываясь на типах аргументов, переданных при вызове.
Таким образом можно создать несколько вариантов функции, которые выполняют аналогичные действия, но принимают разные типы аргументов. Это позволяет создавать более удобный и интуитивно понятный интерфейс для программистов, так как они могут вызывать одно и то же имя функции с разными типами данных, не заботясь о различиях в именах функций.
Перегрузка функций — это возможность определения нескольких функций с одним и тем же именем, но разными параметрами. Когда вызывается такая функция, компилятор определяет, какая из перегруженных функций должна быть вызвана, основываясь на типах аргументов, переданных при вызове.
Таким образом можно создать несколько вариантов функции, которые выполняют аналогичные действия, но принимают разные типы аргументов. Это позволяет создавать более удобный и интуитивно понятный интерфейс для программистов, так как они могут вызывать одно и то же имя функции с разными типами данных, не заботясь о различиях в именах функций.
Как работает std::unique_ptr?
Принцип работы
std::unique_ptr — это умный указатель (smart pointer), предназначенный для управления динамически выделенными объектами. Он обеспечивает автоматическое освобождение памяти при выходе объекта из области видимости или при необходимости.Принцип работы
std::unique_ptr заключается в том, что он владеет указателем на выделенную память и следит за временем жизни этой памяти. Когда объект std::unique_ptr выходит из области видимости, он автоматически освобождает память, на которую он указывает, путем вызова оператора delete для хранящегося указателя.Что такое memory leak?
Утечка памяти может привести к постепенному увеличению объема занятой оперативной памяти программой. Если утечка продолжает развиваться, это может привести к уменьшению производительности программы и даже к завершению программы из-за нехватки доступной памяти.
Memory leak (утечка памяти) — это ситуация, при которой программа использует динамическую память, но забывает освободить эту память перед завершением работы или перед повторным использованием. Как результат, выделенная память остается занята в оперативной памяти, несмотря на то, что она уже не используется, и таким образом происходит утечка памяти.Утечка памяти может привести к постепенному увеличению объема занятой оперативной памяти программой. Если утечка продолжает развиваться, это может привести к уменьшению производительности программы и даже к завершению программы из-за нехватки доступной памяти.
Константные методы
В C++, ключевое слово
Когда вы вызываете константный метод для объекта класса, компилятор гарантирует, что внутри этого метода вы не будете изменять члены данных объекта, кроме членов, объявленных как
В C++, ключевое слово
const имеет различное значение в зависимости от контекста. Оно может быть применено к методам классов для указания, что метод не будет изменять состояние объекта, на котором он вызывается. Такие методы называются «константными методами». Когда вы вызываете константный метод для объекта класса, компилятор гарантирует, что внутри этого метода вы не будете изменять члены данных объекта, кроме членов, объявленных как
mutable (они могут изменяться внутри константных методов).This media is not supported in your browser
VIEW IN TELEGRAM
⚡ Основные алгоритмы на графах
Рассмотрим основные алгоритмы на графах и их реализацию на C++.
Рассматриваемые алгоритмы
▪Обход графа в ширину (Поиск в ширину) aka BFS | Breadth First Search
▪Обход графа в глубину (Поиск в глубину) aka DFS | Depth First Search
▪Алгоритм Дейкстры
▪Алгоритм Флойда-Уоршелла
▪Алгоритм Прима
Смотреть статью
Рассмотрим основные алгоритмы на графах и их реализацию на C++.
Рассматриваемые алгоритмы
▪Обход графа в ширину (Поиск в ширину) aka BFS | Breadth First Search
▪Обход графа в глубину (Поиск в глубину) aka DFS | Depth First Search
▪Алгоритм Дейкстры
▪Алгоритм Флойда-Уоршелла
▪Алгоритм Прима
Смотреть статью
Использование Boost
Если ваш проект открыт для поддержки библиотеки, рассмотрите возможность использования boost::algorithm::join алгоритм. Он объединяет все элементы в указанном списке в строку, где сегменты объединяются заданным разделителем.
Другие способы преобразования вектора в строку можно найти здесь.
Если ваш проект открыт для поддержки библиотеки, рассмотрите возможность использования boost::algorithm::join алгоритм. Он объединяет все элементы в указанном списке в строку, где сегменты объединяются заданным разделителем.
Другие способы преобразования вектора в строку можно найти здесь.
Задача
Найти среднее арифметическое в трех рядах.
Для начала продумаем наше решение. Сразу условимся что длинна ряда у нас будет 5 . Хотите ставьте своё число. Нам надо найти среднее арифметическое в трех рядах, и в каждом по отдельности, т.е. мы сначала сделаем цикл для рядов, а потом в этом цикле сделаем еще один цикл только уже для чисел этого ряда.
Теперь подумаем какие переменные нам понадобятся :
Переменная summa — для суммы чисел каждого ряда
Переменная average — для среднего арифметического каждого ряда
Переменная number — обычное число которое мы будем постоянно прибавлять
Переменные i и j — для циклов, перпенные у нас будут локальные, т.е. использоваться и объявляться и цикле.
Найти среднее арифметическое в трех рядах.
Для начала продумаем наше решение. Сразу условимся что длинна ряда у нас будет 5 . Хотите ставьте своё число. Нам надо найти среднее арифметическое в трех рядах, и в каждом по отдельности, т.е. мы сначала сделаем цикл для рядов, а потом в этом цикле сделаем еще один цикл только уже для чисел этого ряда.
Теперь подумаем какие переменные нам понадобятся :
Переменная summa — для суммы чисел каждого ряда
Переменная average — для среднего арифметического каждого ряда
Переменная number — обычное число которое мы будем постоянно прибавлять
Переменные i и j — для циклов, перпенные у нас будут локальные, т.е. использоваться и объявляться и цикле.
🖼 Axodox machinelearning
Чистая реализация на C++ синтеза изображений на основе стабильной диффузии, включая txt2img, img2img и inpainting.
Github
Чистая реализация на C++ синтеза изображений на основе стабильной диффузии, включая txt2img, img2img и inpainting.
Github
Начало работы с Qt
Минимальный исходный код приложения Qt(часть 1).
QApplication — очень важный класс. Он заботится о входных аргументах, а также о многих других вещах, и в первую очередь о цикле обработки событий . Цикл событий — это цикл, ожидающий ввода данных пользователем в приложениях с графическим интерфейсом.
Давайте скомпилируем это приложение. Нажав на зеленую стрелку в левом нижнем углу, Qt Creator скомпилирует и выполнит его.
И что случилось? Приложение как бы запущено и не отвечает. Это на самом деле нормально. Цикл событий работает и ожидает событий, таких как щелчки мышью в графическом интерфейсе, но мы не предоставили никаких событий для обработки, поэтому он будет выполняться бесконечно.
Давайте добавим что-то для отображения(часть 2). Скомпилируйте его и… вот оно! Наше первое окно!
Минимальный исходный код приложения Qt(часть 1).
QApplication — очень важный класс. Он заботится о входных аргументах, а также о многих других вещах, и в первую очередь о цикле обработки событий . Цикл событий — это цикл, ожидающий ввода данных пользователем в приложениях с графическим интерфейсом.
Давайте скомпилируем это приложение. Нажав на зеленую стрелку в левом нижнем углу, Qt Creator скомпилирует и выполнит его.
И что случилось? Приложение как бы запущено и не отвечает. Это на самом деле нормально. Цикл событий работает и ожидает событий, таких как щелчки мышью в графическом интерфейсе, но мы не предоставили никаких событий для обработки, поэтому он будет выполняться бесконечно.
Давайте добавим что-то для отображения(часть 2). Скомпилируйте его и… вот оно! Наше первое окно!
Пример оконного приложения на C++ Qt
В программе окно создается на основе библиотечного класса QFrame. Этот класс является потомком класса QWidget. Так что можно без всяких проблем заменить в программе QFrame на QWidget.
Подробнее можно почитать здесь.
В программе окно создается на основе библиотечного класса QFrame. Этот класс является потомком класса QWidget. Так что можно без всяких проблем заменить в программе QFrame на QWidget.
Подробнее можно почитать здесь.
#вопросы_с_собеседований
Как работает оператор new в C++ и почему используется именно этот оператор для выделения динамической памяти?
Оператор new используется в C++ для выделения динамической памяти (heap memory), которая выделяется во время выполнения программы. При его вызове, сначала выделяется необходимое количество памяти из операционной системы, а затем возвращается указатель на эту область памяти.
При исполнении оператора new происходит следующее:
1. Сначала он выделяет память в размере, указанном в аргументе оператора или размере типа данных, на который указывает указатель.
2. Затем он вызывает конструктор для создания объекта в выделенной области памяти.
3. Возвращает указатель на выделенную память.
Оператор new является предпочтительным для выделения памяти по сравнению с функцией malloc в C, поскольку он позволяет при выделении памяти автоматически вызывать конструкторы объектов. С использованием оператора new не нужно явно выделять память под объекты и вызывать конструкторы отдельно.
В данном примере оператор new выделяет память под объект класса MyClass и вызывает его конструктор. Оператор delete используется для освобождения ранее выделенной памяти.
Как работает оператор new в C++ и почему используется именно этот оператор для выделения динамической памяти?
Оператор new используется в C++ для выделения динамической памяти (heap memory), которая выделяется во время выполнения программы. При его вызове, сначала выделяется необходимое количество памяти из операционной системы, а затем возвращается указатель на эту область памяти.
При исполнении оператора new происходит следующее:
1. Сначала он выделяет память в размере, указанном в аргументе оператора или размере типа данных, на который указывает указатель.
2. Затем он вызывает конструктор для создания объекта в выделенной области памяти.
3. Возвращает указатель на выделенную память.
Оператор new является предпочтительным для выделения памяти по сравнению с функцией malloc в C, поскольку он позволяет при выделении памяти автоматически вызывать конструкторы объектов. С использованием оператора new не нужно явно выделять память под объекты и вызывать конструкторы отдельно.
В данном примере оператор new выделяет память под объект класса MyClass и вызывает его конструктор. Оператор delete используется для освобождения ранее выделенной памяти.
#вопросы_с_собеседований
Предполагая, что buf является валидным указателем, в чем проблема в приведенном на картинке коде? Каким был бы альтернативный способ реализации этого, который позволил бы избежать этой проблемы?
Проблема в коде заключается в том, что --sz >= 0 всегда будет истинным, поэтому вы никогда не выйдете из цикла while (поэтому вы, вероятно, в конечном итоге испортите память или вызовете какое-то нарушение памяти или какой-либо другой программный сбой, в зависимости от того, что вы делаете внутри цикла). Причина, по которой --sz >= 0 всегда будет истинной, заключается в том, что тип sz равен size_t. size_t на самом деле просто псевдоним одного из основных беззнаковых целочисленных типов. Следовательно, поскольку sz не имеет знака, оно никогда не может быть меньше нуля (поэтому условие никогда не может быть ложным). Одним из примеров альтернативной реализации, позволяющей избежать этой проблемы, может быть использование цикла for следующим образом:
Предполагая, что buf является валидным указателем, в чем проблема в приведенном на картинке коде? Каким был бы альтернативный способ реализации этого, который позволил бы избежать этой проблемы?
Проблема в коде заключается в том, что --sz >= 0 всегда будет истинным, поэтому вы никогда не выйдете из цикла while (поэтому вы, вероятно, в конечном итоге испортите память или вызовете какое-то нарушение памяти или какой-либо другой программный сбой, в зависимости от того, что вы делаете внутри цикла). Причина, по которой --sz >= 0 всегда будет истинной, заключается в том, что тип sz равен size_t. size_t на самом деле просто псевдоним одного из основных беззнаковых целочисленных типов. Следовательно, поскольку sz не имеет знака, оно никогда не может быть меньше нуля (поэтому условие никогда не может быть ложным). Одним из примеров альтернативной реализации, позволяющей избежать этой проблемы, может быть использование цикла for следующим образом:
for (size_t i = 0; i < sz; i++)Ключевое слово requires
Ключевое слово
В примере на картинке
Использование
#для_начинающих
Ключевое слово
requires используется в контексте концепций (concepts) для определения требований, которые тип должен удовлетворять. Концепции представляют собой инструмент в C++, введенный в стандарте C++20, который позволяет более точно указывать ограничения на типы данных, которые могут использоваться в шаблонах.В примере на картинке
Sortable — это концепция, описывающая типы, для которых определены операторы сравнения («<» и «>»). Функция sortAndPrint принимает два аргумента типа T, удовлетворяющего концепции Sortable, и сравнивает их.Использование
requires в данном контексте позволяет более явно указать ограничения на типы данных, которые могут использоваться в шаблонах и функциях, делая код более читаемым и безопасным.#для_начинающих