Строим сами конструктор: Конструктор «Строим сами», 66 деталей (1779169) — Купить по цене от 1 224.00 руб.

С++ — Когда я должен определить свой собственный оператор копирования и присваивания

спросил

Изменено 12 лет, 11 месяцев назад

Просмотрено 3к раз

Я читаю эффективный C++ в статье 5, там упоминаются два случая, в которых я должен сам определить оператор присваивания копии. Case — это класс, который содержит константные и ссылочные элементы.

Я пишу, чтобы спросить, каково общее правило или случай, когда я должен определить свой собственный конструктор копирования и оператор присваивания?

Я также хотел бы знать, когда я должен определить свой собственный конструктор и деструктор.

Большое спасибо!

1

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

  • Вы хотите, чтобы ваш объект был скопирован или присвоен, или помещен в стандартный контейнер, такой как вектор
  • Конструктор копирования по умолчанию и оператор присваивания не будут работать правильно.

Рассмотрим следующий код:

 класс A; // определено в другом месте
класс Б {
частный:
    *my_very_own_a;
};
 

Если позволить конструктору автоматического копирования скопировать B , он скопирует значение указателя A * , так что копия будет указывать на тот же экземпляр A , что и оригинал. Но частью дизайна этого класса является то, что каждый B имеет свой собственный A , поэтому конструктор автоматического копирования нарушил этот контракт. Поэтому вам нужно написать свой собственный конструктор копирования, который создаст новый A для нового B

, на который будет указывать.

Однако рассмотрим этот случай:

 класс А; // определено в другом месте
класс Б {
частный:
    *shared_reference_to_a;
};
 

Здесь каждый B содержит указатель на A , но контракт класса не требует уникального A для каждого B . Таким образом, конструктор автоматического копирования вполне может сделать правильную вещь здесь.

Обратите внимание, что оба примера имеют один и тот же код , но с разными конструктивными особенностями .

Примером первой ситуации может быть B == диалоговое окно, A == кнопка. Если вы создаете копию диалогового окна, возможно, ей также потребуется копия всего содержимого.

Примером второго может быть B == диалоговое окно, A

== ссылка на оконный менеджер. Если вы копируете диалоговое окно, копия, вероятно, существует в том же оконном менеджере, что и оригинал.

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

 CClass::CClass(const CClass& src)
    {
       // эти две точки теперь указывают на одно и то же место в памяти
       // вам действительно нужно выделить новую память
       m_ptr = источник. m_ptr;
       // не имеет большого значения для членов, которые не "указывают" куда-то еще
       // эта копия отлично работает
       m_int = src.m_int;
    }
 

По сути, вы не хотите оказаться в ситуации, когда два экземпляра «указывают» на одно и то же место в памяти. Это может произойти, когда у вас есть указатели в качестве элементов, которые указывают на динамически выделяемую память. Это также может произойти со ссылками, которые ссылаются на что-то вне самого класса. Это может случиться с файловыми дескрипторами, где вам может понадобиться продублировать/повторно открыть новый файл.

На самом деле, последний случай, пожалуй, легче всего осмыслить. Представьте, что у ваших двух объектов C++ есть файл журнала. Без корректно функционирующего конструктора копирования они оба могли бы вести журнал в один и тот же файл. Что произойдет, если в деструкторе классов файл будет закрыт? Что ж, тогда файл журнала второго объекта C++ будет закрыт из-под него. Одним из решений было бы создание конструктора копирования, который создает новый файл для вновь созданного экземпляра.

Поэтому, когда 1-й объект C++ уходит, он не берет с собой файл журнала 2-го объекта C++. У них 2 независимых файла журнала, они не могут мешать друг другу.

Этот пример можно расширить до динамической памяти. Без конструктора копирования у вас будет всего 2 указателя, указывающих на один и тот же адрес. Если деструктор одного удалит эту память, другой может не понять, что память, на которую он указывает, исчезла. Не менее важно и то, что вы, вероятно, не хотите, чтобы один объект записывался в член другого объекта :).

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя адрес электронной почты и пароль

Опубликовать как гость

Электронная почта

Обязательно, но не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

AWS Cloud Development Kit (AWS CDK) v2

Это Руководство разработчика AWS CDK v2. Вошел более старый CDK v1 техническое обслуживание 1 июня 2022 г. и теперь будет получать только исправления критических ошибок и исправления безопасности. Новые функции будут разработаны исключительно для CDK v2. Поддержка CDK v1 будет полностью завершится 1 июня 2023 г.

Конструкции — это основные строительные блоки приложений AWS CDK. Конструкция представляет собой «облако компонент» и инкапсулирует все, что нужно AWS CloudFormation для создания компонента.

Примечание

Конструкции являются частью модели программирования конструкций (CPM). Они также используются другими такие инструменты, как CDK для Terraform (CDKtf), CDK для Kubernetes (CDK8s) и Проджен.

Конструкция может представлять один ресурс AWS, например корзину Amazon Simple Storage Service (Amazon S3). А конструкция также может быть абстракцией более высокого уровня, состоящей из нескольких связанных ресурсов AWS. Примеры таких компонентов включают рабочую очередь с соответствующей вычислительной мощностью или запланированное задание с ресурсами мониторинга и панелью управления.

AWS CDK включает коллекцию конструкций, называемую библиотекой конструкций AWS, содержащую конструкции для каждого сервиса AWS. Construct Hub — это ресурс, который поможет вам найти дополнительные конструкции из AWS, третьи стороны и сообщество CDK с открытым исходным кодом.

Важно

В AWS CDK v1 базовый класс Construct находился в ядре CDK модуль. В CDK v2 есть отдельный модуль с именем , конструкции , которые содержит этот класс.

Библиотека AWS Construct

CDK AWS включает библиотеку AWS Construct, который содержит конструкции, представляющие ресурсы AWS.

Эта библиотека включает конструкции, представляющие все ресурсы, доступные в AWS. За например, класс s3.Bucket представляет корзину Amazon S3, а класс dynamodb.Table представляет таблицу Amazon DynamoDB.

Конструкции L1

В этой библиотеке есть три разных уровня конструкций, начиная с низкоуровневого конструкции, которые мы называем Ресурсы CFN (или L1 , сокращение от «уровень 1»).

Эти конструкции непосредственно представляют все ресурсы доступны в AWS CloudFormation. Ресурсы CFN периодически генерируются из ресурса AWS CloudFormation. Спецификация. Они называются Cfn Xyz , где Xyz — имя ресурс. Например, CfnBucket представляет ресурс AWS::S3::Bucket AWS CloudFormation. Когда вы используете ресурсы Cfn, вы должны явно настроить все свойства ресурса. Это требует полного понимания деталей базовая модель ресурсов AWS CloudFormation.

Конструкции L2

Конструкции следующего уровня, L2 , также представляют AWS ресурсы, но с высокоуровневым API на основе намерений. Они обеспечивают аналогичную функциональность, но включите значения по умолчанию, шаблонную логику и связующую логику, которую вы бы написали сами с помощью Ресурсная конструкция CFN. Конструкции AWS предлагают удобные значения по умолчанию и избавляют от необходимости знать все сведения о ресурсах AWS, которые они представляют.

Они также предоставляют удобные методы которые упрощают работу с ресурсом. Например, класс s3.Bucket представляет корзину Amazon S3 с дополнительными свойствами и методами, такими как Bucket.addLifeCycleRule(), который добавляет в корзину правило жизненного цикла.

Конструкции L3

Наконец, библиотека конструкций AWS включает конструкции L3 , которые мы называем шаблонами . Эти конструкции предназначены для помочь вам выполнять стандартные задачи в AWS, часто с использованием нескольких видов ресурсов. За Например, конструкция aws-ecs-patterns.ApplicationLoadBalancedFargateService представляет архитектура, включающая контейнерный кластер AWS Fargate, использующий Application Load Balancer. Конструкция aws-apigateway.LambdaRestApi представляет собой API Amazon API Gateway, поддерживаемый функцией AWS Lambda.

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

Композиция

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

С точки зрения «снизу вверх» вы используете конструкции для организации отдельных AWS ресурсы, которые вы хотите развернуть. Вы используете любые абстракции, удобные для вашего цель, с таким количеством слоев, как вам нужно.

Композиция позволяет определять повторно используемые компоненты и совместно использовать их, как и любой другой код. За Например, команда может определить конструкцию, которая реализует лучшие практики компании для DynamoDB. таблица с резервным копированием, глобальной репликацией, автоматическим масштабированием и мониторингом. Команда может поделиться конструкцию с другими командами в своей организации или публично.

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

Инициализация

Конструкции реализованы в классах, расширяющих базу Construct класс. Вы определяете конструкцию, создавая экземпляр класса. Все конструкции принимают три параметра когда они инициализированы:

  • Область

    — родитель или владелец конструкции, либо стек или другая конструкция, определяющая ее место в дереве конструкций. Обычно вы должны пройти это (или self в Python), который представляет текущий объект, для размаха.

  • id — идентификатор, который должен быть уникальным в пределах этой области. Идентификатор служит пространство имен для всего, что определено в текущей конструкции. Он привык генерировать уникальные идентификаторы, такие как ресурс имена и логические идентификаторы AWS CloudFormation.

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

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

Приложения и стеки

Мы называем ваше приложение CDK приложением , которое представлено Приложение класса AWS CDK. В следующем примере определяется приложение с одним стеком, содержащим одна корзина Amazon S3 с включенным управлением версиями:

Как видите, вам нужна область, в которой можно определить вашу корзину. Ресурсы в конце концов необходимо развернуть как часть стека AWS CloudFormation в среде AWS . Среда охватывает определенный Аккаунт AWS и регион AWS. конструкции AWS, такие как s3.Ведро , должно быть определяется в рамках стека.

Стеки

в приложениях AWS CDK расширяют базовый класс Stack , т.к. показано в предыдущем примере. Следующий пример является распространенным шаблоном при создании стека. в вашем приложении AWS CDK. Он показывает, как расширить стек . class, определите конструктор, который принимает scope , id и props , и вызовите базу конструктор класса через super с полученным прицелом , id и реквизитом .

Использование конструкций L1

После того, как вы определили стек, вы можете заполнить его ресурсами, создав экземпляр конструкции. Во-первых, мы сделаем это с конструкцией L1.

Конструкции L1 — это именно те ресурсы, которые определены AWS CloudFormation, ни больше, ни меньше. Ты должен предоставить необходимую конфигурацию ресурса самостоятельно. Вот, например, как создать Корзина Amazon S3 с использованием CfnBucket класс. (Вы увидите аналогичное определение, используя Класс Bucket в следующем разделе.)

Свойства конструкции, которые не являются простыми логическими значениями, строками, числами или контейнерами, на поддерживаемых языках обрабатываются по-разному.

Важно

Нельзя использовать типы свойств L2 с конструкциями L1 и наоборот. При работе с L1 конструкции, всегда используйте типы, определенные для используемой вами конструкции L1. Не используйте типы из других конструкций L1 (некоторые из них могут иметь такое же имя, но не одного типа).

Некоторые из наших ссылок на API для конкретных языков в настоящее время содержат ошибки в путях к L1. типы свойств или вообще не документируйте эти классы. Мы надеемся исправить это в ближайшее время. в тем временем помните, что такие типы всегда являются внутренними классами конструкции L1, они используется с.

Использование конструкций L2

В следующем примере корзина Amazon S3 определяется путем создания экземпляра класса Bucket , конструкции L2.

Библиотека конструкций AWS включает конструкции, представляющие многие Ресурсы.

Примечание

MyFirstBucket — это не имя корзины, которую создает AWS CloudFormation. Это логический идентификатор, присвоенный новой конструкции. См. физические имена для деталей.

Конфигурация

Большинство конструкций принимают свойства в качестве третьего аргумента (или в Python ключевое слово arguments), коллекция имя/значение, которая определяет конфигурацию конструкции. Следующий Пример определяет корзину с шифрованием службы управления ключами AWS (AWS KMS) и включенным размещением статического веб-сайта. Поскольку в нем явно не указан ключ шифрования, Ковш конструкция определяет новый kms.Key и связывает его с ведром.

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

Взаимодействие с конструкциями

Конструкции — это классы, расширяющие базовый класс Construct. После тебя создать экземпляр конструкции, объект конструкции предоставляет набор методов и свойств, которые позволяют вы взаимодействуете с конструкцией и передаете ее как ссылку на другие части система.

Платформа AWS CDK не накладывает никаких ограничений на API конструкций. Авторы могут определить любой API, который они хотят. Однако конструкции AWS, входящие в состав AWS Создайте библиотеку, такую ​​как s3.Bucket , следуйте рекомендациям и общим шаблонам. Этот обеспечивает согласованное взаимодействие со всеми ресурсами AWS.

Большинство конструкций AWS имеют набор разрешений методы, которые можно использовать для предоставления разрешений AWS Identity and Access Management (IAM) для этой конструкции главный. В следующем примере предоставляется группа IAM наука о данных разрешение для чтения из корзины Amazon S3 raw-data .

Другим распространенным шаблоном для конструкций AWS является установка одного из атрибутов ресурса из данных, предоставленных в другом месте. Атрибуты могут включать имена ресурсов Amazon (ARN), имена или URL-адреса.

Следующий код определяет функцию AWS Lambda и связывает ее с Amazon Simple Queue Service. (Amazon SQS) через URL-адрес очереди в переменной среды.

Сведения о наиболее распространенных шаблонах API в библиотеке конструкций AWS см. Ресурсы.

Написание собственных конструкций

В дополнение к использованию существующих конструкций, таких как s3.Bucket , вы также можете написать ваши собственные конструкции, а затем любой может использовать их в своих приложениях. Все конструкции равны в CDK AWS. Конструкция AWS CDK (например, s3.Bucket или sns.Topic ) ведет себя так же, как конструкция из сторонней библиотеки, опубликованная через NPM, Maven или PyPI. Конструкции, опубликованные во внутреннем репозитории пакетов вашей компании, также ведут себя одинаково. способ.

Чтобы объявить новую конструкцию, создайте класс, расширяющий базовый класс Construct, в создает пакет , затем следует шаблону для инициализатора аргументы.

В следующем примере показано, как объявить конструкцию, представляющую корзину Amazon S3. Корзина S3 отправляет уведомление Amazon Simple Notification Service (Amazon SNS) каждый раз, когда кто-то загружает файл в Это.

Примечание

Наш NotificationBucket 9Конструкция 0025 наследует не Bucket , а точнее из Конструкт . Мы используем композицию, а не наследование, чтобы связать Корзина Amazon S3 и тема Amazon SNS вместе. В общем, состав предпочтительнее, чем наследование при разработке конструкций AWS CDK.

Конструктор NotifyingBucket имеет типичную сигнатуру конструкции: прицел , id и реквизит . Последний аргумент, реквизит не является обязательным (получает значение по умолчанию {} ), потому что все реквизиты являются необязательными. (Базовый класс Construct не принимает реквизит аргумент. ) Вы можете определить экземпляр этой конструкции в своем приложении без props , например:

Или вы можете использовать props (в Java дополнительный параметр) для указания пути префикс для фильтрации, например:

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

Теперь потребители могут подписаться на тему, например:

Дерево конструкций

Как мы уже видели, в приложениях AWS CDK вы определяете конструкции «внутри "другие конструкции используя аргумент области , передаваемый каждой конструкции. Таким образом, приложение AWS CDK определяет иерархию конструкций, известную как дерево конструкций .

Корнем этого дерева является ваше приложение, то есть экземпляр Приложение класс. В приложении вы создаете один или несколько стеков. Внутри стеков вы создаете экземпляры либо ресурсы AWS CloudFormation, либо конструкции более высокого уровня, которые сами могут создавать экземпляры ресурсов или другие конструкции, и так далее вниз по дереву.

Конструкции всегда явно определены в рамках другого конструкта, так что нет никаких сомнений в отношениях между конструктами. Почти всегда вы должен пройти это (в Python self ) в качестве области действия, указывающей, что новая конструкция является потомком текущей конструкции. Предполагаемый шаблон заключается в том, что вы получаете ваш конструкт из конструкт , то создавать экземпляры конструкций, которые он использует в своем конструкторе.

Явная передача области позволяет каждой конструкции добавлять себя в дерево, с этим поведение полностью содержится в базовом классе Construct . Он работает одинаково на всех языках, поддерживаемых AWS CDK, и не требует самоанализ или другая «магия».

Важно

Технически можно передать какую-либо область, отличную от , в этом , когда создание экземпляра конструкции. Вы можете добавлять конструкции в любом месте дерева или даже в другом месте. стек в том же приложении. Например, вы можете написать функцию в стиле миксина, которая добавляет конструкции для области, переданной в качестве аргумента. Практическая трудность здесь в том, что вы не может легко гарантировать, что идентификаторы, которые вы выбираете для своих конструкций, уникальны для кого-то чужая сфера. Эта практика также делает ваш код более трудным для понимания, сопровождения и повторное использование. Почти всегда лучше найти способ выразить свое намерение, не прибегая к злоупотребление область действия аргумент.

AWS CDK использует идентификаторы всех конструкций на пути от корня дерева к каждому дочернему элементу для создания уникальных идентификаторов, необходимых для AWS CloudFormation. Этот подход означает, что идентификаторы конструкций должны быть уникальными только в пределах своей области, а не во всем стеке, как в нативном Облачное формирование AWS. Однако, если вы переместите конструкцию в другую область, ее сгенерированный уникальный идентификатор стека изменения, и AWS CloudFormation не будет считать его одним и тем же ресурсом.

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

  • node.children — Прямые дочерние элементы конструкции.

  • node.id — идентификатор конструкции в пределах ее области действия.

  • node.path — Полный путь к конструкции, включая идентификаторы всех его родителей.

  • node.root — Корень дерева построения (приложение).

  • node.scope — Область (родительская) конструкции или не определено, если узел является корнем.

  • node.scopes — Все родители конструкции, вплоть до корня.

  • node.uniqueId — уникальный буквенно-цифровой идентификатор для этого построить в дереве (по умолчанию создается из node.path и хэш).

Дерево конструкций определяет неявный порядок, в котором конструкции синтезируются для ресурсы в окончательном шаблоне AWS CloudFormation. Где один ресурс должен быть создан раньше другого, AWS CloudFormation или AWS Construct Library обычно определяют зависимость.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *