|
|
|||||||
С++ идиомы31.07.2016, 19:20. Показов 147871. Ответов 34
Метки нет (Все метки)
Перевод статей 1 и 2. Будет постепенно обновляться. Желающие внести вклад могут писать в ЛС.
Переведенные идиомы: self-assignment in an assignment operator Scope Guard Shrink-to-fit Checked delete Pointer To Implementation Получение адреса(ака взятие адреса aka Address-of) nullptr Iterator Pair Coercion by Member Template
14
|
|||||||
| 31.07.2016, 19:20 | |
|
Ответы с готовыми решениями:
34
С++ идиомы - обсуждение
|
| 01.08.2016, 11:33 | ||||||
|
Scope Guard
Задачи: Гарантировать освобождение ресурсов при возникновении исключения, но не освобождать ресурсы при нормальном завершении. Предоставить базовую гарантию безопасности исключений. Мотивация: Идиома RAII позволяет захватывать ресурсы в конструкторе и освобождать их в деструкторе, при достижении конца области видимости или из-за исключения. В RAII ресурс освобождает всегда. Это может быть не очень гибким решением. Может потребоваться освободить ресурсы в случае возникновения исключения и не освобождать при нормальном завершении. Решение и пример кода: Типичная реализация идиомы RAII с проверкой необходимости освобождения ресурса.
9
|
||||||
|
|
|||||||||||
| 01.08.2016, 11:54 [ТС] | |||||||||||
|
self-assignment in an assignment operator (самоприсваивание в операторе присваивания)
T::operator= который обрабатывает случай, где левый и правый операнды являются одним и тем же объектом.
Понимайте разницу между идентичностью (левый и правый операнды являются одним объектом) и одинаковостью (левый и правый операнды имеют одинаковые значения).T::operator= должен защищать себя в случае индетичности объектов, код присваивания может быть удобным и безопастным предполагая, что работает с разными объектами. Существуют и другие техники, которые в некоторых случаях могут быть более удобными, но они не применимы во всех ситуациях. Например если все члены класса T (скажем mem1, mem2, ..., memN) предоставляют функцию swap(), то можно использовать следующий код
6
|
|||||||||||
| 01.08.2016, 20:51 | |||||||||||
|
Shrink-to-fit (уменьшить до размеров)
Задачи: Уменьшить ёмкость (capacity) контейнера, до размера, достаточного для содержания элементов. Также известен как "Swap-To-Fit", введенный Скотом Майерсом в книге "Effective STL" ("Эффективное использование STL"). Мотивация: Контейнеры в стандартной библиотеке часто выделяют памяти под большее число элементов, чем находится в контейнере. Это позволяет оптимизировать расширение контейнера за счет более редких выделений памяти. Но, когда контейнер уменьшается (или когда запас израсходаван не полностью, прим. переводчика), память так и остается занятой, хотя, фактически, она не используется. Это не нужный перерасход памяти. Данная (shrink-to-fit) идиома была разработана чтобы уменьшить расход до минимального требуемого контейнеру количества памяти, тем самым экономя ресурсы. Решение и пример кода: Данная идиома очень проста, как показано ниже.
std::vector<int>(v), создает временный вектор целых чисел, гарантируя, что выделенной памяти достаточно для хранения всех элементов вектора v, который передан в параметре. Также эти элементы копируются во временный вектор.Вторая половина инструкции - .swap(v) обменивает элементы вектора v и временного вектора, используя не выбрасывающую исключений функцию-член swap, что является очень эффективным средством, которое сводится к обмену внутренних указателей между векторами или чуть более того. После этого временный вектор удаляется, очищая память и удаляя элементы, которые первоначально находились в векторе v. Вектор v же имеет ровно столько памяти, сколько нужно для хранения элементов. ISO/IEC 14882:1998 не гарантирует такое поведение для конструктора копирования. Как гарантировать такое поведение? Более надежным решением (в частности std::string и std::vector могут быть реализованы с использованием подсчета ссылок и тогда конструктор копирования может "скопировать" всю избыточную память) будет использование конструктора диапазонов, вместо конструктора копирования:
В C++11 некоторые контейнеры предоставляют функцию-член shrink_to_fit, например vector, deque, basic_string. shrink_to_fit запрашивает уменьшение capacity до size, Но данный запрос не является обязательным к исполнению.
8
|
|||||||||||
| 01.08.2016, 20:51 | |||||||||||||||||||||||||||
|
Checked delete
Цель: Повышение безопасности при использовании delete expression. Мотивация и пример проблемного кода: Стандарт C++ (пункт 5.3.5/5) позволяет использовать в delete-expression указатель на не полный тип, но при этом, если деструктор или функция освобождения памяти объекта не являются тривиальными, то это приведет к неопределенному поведению.
В следующем примере в main.cpp определяется объект типа Object. В функции main() вызывается функция delete_object(), определенная в deleter.cpp, где нет определения класса Object, а есть лишь его объявление. Вызов delete в данной функции приводит к неопределенному поведению.
Идиома checked delete полагается на вызов шаблонной функции для удаления объекта, а не на прямой вызов delete, который может привести к неопределенному поведению для объявленных, но неопределенных типов. Ниже приводится реализация шаблонна функции boost::checked_delete из Boost Utility library.Её использование вызывает ошибку компиляции при использовании sizeof для параметра шаблона T, если T - не полный тип. Если T объявлен, но не определен, то sizeof(T) будет генерировать ошибку компиляции или возвращать нулевое значение, в зависимости от компилятора. Если sizeof(T) вернет ноль, то произойдет ошибка компиляции, т.к. объявляется массив с отрицательным количеством элементов (-1). Имя type_must_be_complete в данном случае появляется в сообщении об ошибке и позволяет понять что произошло.
delete[].Предупреждение: std::auto_ptr не использует никакого эквивалента checked delete. Поэтому инстанцирование std::auto_ptr с неполным типом может привести к неопределенному поведению в деструкторе, если в момент объявления std::auto_ptr тип параметра шаблона определен не полностью.
12
|
|||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||
| 02.08.2016, 08:12 [ТС] | |||||||||||||||||||||||||||||||
|
Pointer To Implementation (pImpl)
Идиома "pointer to implementation" (pImpl) также называется "opaque pointer" (дословный перевод "непрозрачный указатель"), это способ предоставления данных и в еще один уровень абстракции в реализации классов. В С++ вы должны написать декларацию переменных-членов класса внутри определения класса, эти члены должны быть публичны (прим. переводчика - думаю речь идет об интерфейсе, иначе зачем членам быть публичными) и поскольку для членов выделяется память абстракция реализации не возможна для "всех" классов. Тем не менее, за счет дополнительного указателя и вызова функции, вы можете иметь такой уровень абстракции через указатель на реализацию. Допустим вы написали такой класс:
pImpl может реализовывать следующий паттерн таким образом, что описанная выше ситуация не является проблемой.
8
|
|||||||||||||||||||||||||||||||
|
☆ Форумчанин(FSC)☆
|
|||||||||||
| 09.08.2016, 19:40 | |||||||||||
|
Получение адреса(ака взятие адреса aka Address-of)
Назначение: Поиск адреса обьекта класса который имеет перегруженный унарный оператор "амперсанд"(&). Интерес: Язык С++ разрешает перегрузку унарного амперсанда (&) для классовых типов. Тип возвращаемого значения не обязательно должен быть реальным адресом обьекта . Предназначение такого класса довольно спорно, но все же язык позволяет это.Идиома взятия адреса это способ получения реального адреса обьекта, независимого от перегруженного унарного амперсанда и его инкапсулированости. В примере ниже не удается скомпилировать функцию main потому что оператор & класса nonaddressable является закрытым членом этого класса.
Идиома получения адреса запрашивает адрес обьекта используя серию преобразований
Используется в библиотеке boost для получения адреса Эта функция уже пристутствует в заголовке <memory> нового стандарта C++(C++ 11)
2
|
|||||||||||
|
161 / 153 / 92
Регистрация: 18.11.2015
Сообщений: 677
|
|||||||||||||||||||||||||||||||||||||||||
| 16.08.2016, 15:46 | |||||||||||||||||||||||||||||||||||||||||
|
Nullptr
Задачи: Научиться отличать число 0 от нулевого указателяМотивация: На протяжении многих лет С++ имело позорный недостаток, у С++ не было ключевого слова, которое бы обозначало нулевой указатель. С++ 11 избавился от этого недостатка. Строгая типизация С++ делает определение глобальной константы NULL в стиле языка C почти что бесполезной в выражениях, например:
Проблема самого первого примера в том, что С++ запрещает приведение из типа void *, даже когда его значение является константным нулем. Но, для простого константного нуля С++ имеет преобразование int в указатель (еще short в указатель, long в указатель и т.п.).Это имеет свои минусы. Приведем пример на работе с перегруженными функциями:
main превратиться в:
#define NULL 0 так, как задумывалось (с указателями), нужно всегда писать что типа static_cast<double *>(NULL)Использование #define NULL 0 имеет свою кучку проблем. Помимо проблемы с перегруженными функциями, C++ требует того, чтобы NULL было определено целочисленным константным выражением со значением 0. Поэтому, в отличии от С, нулевой указатель не может быть определен как ((void *)0) в стандартной библиотеке C++. Более того, конкретная форма определения оставлена для той или иной реализации, что значит, что 0 и 0L - подходящие определения, наряду с некоторыми другими.Решение и пример использования Идиома нулевого указателя решает некоторые вышеперечисленные проблемы и может быть использована снова и снова. Будущий пример является очень близким по функционалу решением, относительно ключевого слова nullptr, добавленного в С++ 11, и использует только стандартные приемы, которые были доступны еще до С++ 11.
#include класса выше)
nullptr с указателем на функцию-член (pmf). Код выше успешно компилируется, если убрать строки с ошибками, которые мы допустили в демонстрационных целях (26, 31, 34, 35, 40, 41, 42, 50)Заметьте, что идиома нулевого указателя использует идиому Return Type Resolver, чтобы автоматически вывести нулевой указатель правильного типа, в зависимости от типа объекта, к которому мы его присваиваем. Например, если nullptr присваивают к char *, создается функция преобразования с char параметром шаблона.Последствия Есть некоторые недостатки этого приема, в список этих недостатков входят следующие пункты:
5
|
|||||||||||||||||||||||||||||||||||||||||
|
Мозгоправ
|
|||||||||||||||||||||
| 03.11.2019, 18:47 | |||||||||||||||||||||
|
Iterator Pair
Итераторная пара Задача Определить диапазон значений данных, без привязки к базовой структуре, которая используется этими значениями. Также известно как Иногда это называют итераторным диапазоном (Iterator Range). Проблема Хорошо известно, что для создания вектора vector<int> из другого vector<int> используется конструктор копии. Также для создания вектора vector<int> из другого vector<int> можно использовать идиому Приведение типа посредством шаблонного метода (Coercion by Member Template), применённую к конструктору шаблонного члена. Пример кода показан ниже.
Решение и пример кода Пара итераторов используется для обозначения начала и конца диапазона значений. Благодаря шаблону проектирования итераторов, кто бы ни использовал эту идиому (в нашем примере для вектора), может получить доступ к диапазону, абстрагируясь от деталей реализации структуры данных. Единственное требование заключается в том, что итераторы должны предоставлять минимальный фиксированный интерфейс. Например, предоставлять оператор префиксного инкремента.
set<T>::iterator или list<T>::iterator или массив POD. Независимо от типа, любой общий алгоритм, написанный в терминах итераторных пар, работает. Часто полезно показать, что модель должна реализовывать итераторные типы. В приведенном выше примере итераторы требуют от модели наличия как минимум InputIterator. Более подробная информация о категориях (тегах) итераторов и их использовании описана в идиоме Диспетчеризация тегов.Иногда без использования идиомы итераторной пары обойтись невозможно. Например, при создании std::string из буфера символов, в котором присутствуют нулевые символы, применение идиомы итераторной пары просто необходимо.
Все стандартные контейнеры. Связанные идиомы
1
|
|||||||||||||||||||||
|
Мозгоправ
|
||||||||||||||||
| 05.11.2019, 14:53 | ||||||||||||||||
|
Coercion by Member Template
Приведение типа посредством шаблонного метода Задача Повысить гибкость интерфейса шаблонного класса, позволяя шаблону класса участвовать в тех же неявных преобразованиях типов, что и его типы-параметры. Проблема Часто бывает полезно расширить отношения между двумя типами до специализации шаблонов классов с этими типами. Например, предположим, что класс D наследуется от класса B. Указатель на объект класса D может быть присвоен указателю на класс B. C++ поддерживает это неявным образом. Однако типы, составленные из этих типов, не разделяют отношения родительских типов. Это относится и к шаблонам классов, поэтому объект Helper<D> обычно нельзя присвоить объекту Helper<B>.
std::unique_ptr<D> в std::unique_ptr<B>. Это интуитивно понятно, но не поддерживается без использования идиомы Приведение типа посредством шаблонного метода.Решение и пример кода Определите в шаблонном классе шаблонные методы, которые полагаются на неявные преобразования типов, которые поддерживаются типами параметров. В следующем примере шаблонный конструктор и оператор присваивания работают для любого типа U, для которого разрешена инициализация или присвоение T* из U*.
D унаследован от класса B, D-объект является B-объектом. Однако массив объектов D не является массивом объектов B. Это запрещено в C++ из-за возможного неправильного вычисления размера массива на основании размера элемента. (Объект производного класса, скорее всего, будет занимать больше памяти, чем объект базового класса. Поэтому если предположить, что массив D-объектов, это массив B-объектов, то часть массива будет утеряна при расчёте объёма занимаемой памяти, исходя из размера B-объекта, а остальные объекты, за исключением первого, будут некорректны из-за неправильного позиционирования на начало объекта. – прим. перев.) Ослабление этого правила для множества указателей может быть полезным. Например, массив указателей на D должно быть возможно присвоить массиву указателей на B (при условии, что деструктор B является виртуальным). Этого можно достичь с помощью рассматриваемой идиомы, но требуется дополнительная осторожность, чтобы предотвратить копирование массива указателей на базовый тип в массив указателей на производный тип. Для этого можно использовать специализации шаблонных методов или SFINAE.В следующем примере используется шаблонный конструктор и шаблонный оператор присваивания. Из-за объявления Array<U *> они будут разрешать копирование массивов указателей только тогда, когда типы элементов различаются.
std::unique_ptr и std::shared_ptr, используют эту идиому.Предостережения Типичной ошибкой в реализации идиомы Приведения типа посредством шаблонного метода является отсутствие нешаблонного конструктора копирования или нешаблонного копирующего оператора присваивания при наличии шаблонного конструктора копирования и шаблонного копирующего оператора присваивания. Компилятор автоматически создаёт конструктор копирования и копирующий оператор присваивания, если класс не объявляет их, что может вызвать скрытые и неочевидные ошибки при использовании этой идиомы. Известные применения
Связанные идиомы
1
|
||||||||||||||||
|
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
|
||||||
| 12.02.2021, 16:38 | ||||||
----------- добавлю линк на pdf - про Exception Safety, включая RAII - Using Exceptions | C++ - using RAII] for cleanup ... вообще Exception Safety - очень интересная тема - очень нравится идея
![]() ===== Добавлено через 11 минут Добавлено через 28 минут ===== в Qt часто используется идиома pImpl для Widget'ов, например, для описания родительского окна и его потомков... в используемом мной U++ это не совсем актуально в таком разрезе, поскольку наследования ЭУ как такового нет (они все независимы - главное правильно расставлять конструкторы и деструкторы, согласно RAII, полагаю)... имхо и кстати, используя pImpl, - вы теряете возможность использовать inline (хотя последнего современные компиляторы в принципе воспринимают как попало)... и вижу пользу в использовании идиомы pImpl - например, при создании части интерфейса на C++ с выносом этой части в отдельную реализацию, чтобы основная часть основного класса, написанного на С, могла использовать этот свой stuff на С++ ... - т.к. правила дурного тона - смешивать C и C++ и неуважение к компилятору смешивать языки... имхов общем, часто городить pImpl - это просто усложнять себе сопровождаемость кода, но обоснованное использование принесёт свои удобства... имхо Добавлено через 19 минут конечно, можно разделить интерфейс и реализацию и с помощью чисто абстрактного класса, но тогда мы вынуждены иметь дело с vtable в run-time'e ... но, используя идиому pImpl и уходя от необходимость иметь дело с vtable в run-time'e, улучшим ли мы performance нашего app, - спорно и не всегда, если нам всё равно приходится выделять доп. память под скрытый объект в придачу к основному объекту... + сокрытие части реализации в др. классе, требует подробного описания возможных побочных эффектов этой скрытой части на основной класс хотя бы в документации... вот как-то так Добавлено через 3 минуты ведь всегда интересно WHEN to use и каковы Последствия
0
|
||||||
|
Неэпический
|
|||
| 14.02.2021, 12:22 | |||
|
RAII - отдельный от исключений механизм, конечно же всегда и программа должна быть запущена и исключение перехвачено и всё остальное должно быть правильно. Что касается std::terminate, то он вызывается, но вот остальное зависит от реализации. http://eel.is/c++draft/except#handle-9
0
|
|||
|
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
|
||
| 14.02.2021, 13:08 | ||
|
0
|
||
|
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
|
||||||||
| 14.03.2021, 16:53 | ||||||||
как-то разорвано всё на wiki... простое наследование от Астахова - в стиле CRTP с возможностью использовать объекты в полиморфном контейнере - рабочий вариант так:
Кликните здесь для просмотра всего текста
при этом передали rowPointer в std::unique_ptr и удалили при выходе из scope...
критические замечания всегда приветствуются... лучше кодом Добавлено через 19 минут и наблюдения:
0
|
||||||||
|
фрилансер
6421 / 5617 / 1125
Регистрация: 11.10.2019
Сообщений: 14,928
|
|||
| 14.03.2021, 20:26 | |||
|
Добавлено через 2 минуты
1
|
|||
|
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
|
||||||||
| 14.03.2021, 20:36 | ||||||||
|
но, полагаю, можно и так
0
|
||||||||
|
фрилансер
6421 / 5617 / 1125
Регистрация: 11.10.2019
Сообщений: 14,928
|
||
| 14.03.2021, 20:43 | ||
|
JeyCi, да, я слегка ошибся - у тебя запутанная архитектура ) Утечки не будет
но зачем такие пляски, если вместо new сразу создать умный указатель через make_unique? Зачем метод clone? Добавлено через 54 секунды Добавлено через 2 минуты ещё у меня опасение, что мы тут оффтопим
0
|
||
|
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
|
|||
| 14.03.2021, 21:05 | |||
|
часто CRTP описывается только с template'ом и наследниками - а дальше пляски и не всегда работает, как положено... в частности полиморфное поведение в полиморфном контейнере... ещё потестить можно обычные примеры, но этот про запас не помешает...
0
|
|||
| 14.03.2021, 21:05 | |
|
Помогаю со студенческими работами здесь
20
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
| Опции темы | |
|
|
Новые блоги и статьи
|
||||
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|
Фото: Daniel Greenwood
kumehtar 13.11.2025
|
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга,
Ты же видел моря и метели.
Как сменялись короны и стяги,
Как эпохи стрелою летели.
- Этот мир — это крылья и горы,
Снег и пламя, любовь и тревоги,
И бескрайние. . .
|
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1
У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\
А в самом низу файла-профиля. . .
|
|
PowerShell и онлайн сервисы. Валюта (floatrates.com руб.)
iNNOKENTIY21 11.11.2025
PowerShell функция floatrates-rub
Примеры вызова:
# Указанная валюта 'EUR'
floatrates-rub -Code 'EUR'
# Список имеющихся кодов валют
floatrates-rub -Available
function floatrates-rub {
|
PowerShell и онлайн сервисы. Погода (RP5.ru)
iNNOKENTIY21 11.11.2025
PowerShell функция Get-WeatherRP5rss для получения погоды с сервиса RP5
Примеры вызова
Get-WeatherRP5rss
с указанием id 5484 — Москва (восток, Измайлово) и переносом строки:. . .
|
PowerShell и онлайн сервисы. Погода (wttr)
iNNOKENTIY21 11.11.2025
PowerShell Функция для получения погоды с сервиса wttr
Примеры вызова:
Погода в городе Омск с прогнозом на день, можно изменить прогноз на более дней, для этого надо поменять запрос:. . .
|
PowerShell и онлайн сервисы. Валюта (ЦБР)
iNNOKENTIY21 11.11.2025
# Получение курса валют
function cbr (] $Valutes = @('USD', 'EUR', 'CNY')) {
$url = 'https:/ / www. cbr-xml-daily. ru/ daily_json. js'
$data = Invoke-RestMethod -Uri $url
$esc = 27
. . .
|
И решил я переделать этот ноут в машину для распределенных вычислений
Programma_Boinc 09.11.2025
И решил я переделать этот ноут в машину для распределенных вычислений
Всем привет. А вот мой компьютер, переделанный из ноутбука.
Был у меня ноут асус 2011 года. Со временем корпус превратился. . .
|