Почему в C ++ для allocator нужен конструктор копирования? - PullRequest
11 голосов
/ 21 августа 2011

Говорят здесь , что это из-за спецификации исключения. Я не понимаю. Имеет ли этот вопрос какое-либо отношение к спецификации исключений?

Ответы [ 4 ]

9 голосов
/ 21 августа 2011

Прочитав урок, я немного запутался в формулировке.Но я считаю, что все так просто: в учебнике объяснялось, почему заголовок шаблона распределителя показывает

allocator(const allocator&) throw();

и

template <class U> allocator(const allocator<U>&) throw();

хотя конструктор копирования довольно бесполезен для распределителя.И ответ был таков: спецификация распределителя не позволяет конструктору генерировать исключения.Поэтому открытый интерфейс конструктора копирования определяет конструкторы копирования со спецификацией исключений throw() (не генерирует никаких исключений), чтобы не допустить, чтобы кто-то извлекал свой собственный распределитель с конструкторами копирования, которые могли бы вызвать исключение.эта ссылка для хорошего описания того, что такое спецификация исключения, если это то, что вас сбрасывает.(Не каламбур предназначен. Действительно.)

Таким образом, они не означали, что при создании распределителя вы должны предоставить конструктор копирования.Они просто указывали, что спецификация специально запрещает вам определять тот, который выбрасывает любые исключения.`

4 голосов
/ 21 августа 2011

Вы должны явно написать конструктор копирования (а не использовать значение по умолчанию), потому что конструктор копирования для распределителя C ++ 03 должен быть определен со спецификатором исключения throw().Конструктор копирования по умолчанию не имеет этого спецификатора.

Технически, у вас нет to, но если он выдает исключение ... что ж, удачи в этом.

Но это всего лишь небольшое раздражение, поскольку распределители в C ++ 03 не могут иметь состояния.Так что вы не должны копировать участников.Конструктор копирования может быть пустым.

2 голосов
/ 21 августа 2011

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

1 голос
/ 02 сентября 2017

Это на самом деле довольно просто.Конструктор контейнера, использующий распределитель, берет распределитель и сохраняет его копию.Для этого ему нужно, чтобы распределитель был CopyConstructible.Это все.Обратите внимание, что тип распределителя не требуется для CopyAssignable, если его признак propagate_on_container_copy_assignment не является истинным (что встречается редко).

В спецификации C ++ 11 также говорится, что «Нет конструктора, оператора сравнения, операции копирования,Операция перемещения или операция обмена на этих типах должна завершаться через исключение ".Правила исключений позволяют вам делать (стековую) копию распределителя (особенно во время создания или уничтожения), не беспокоясь о том, что копирование распределителя произойдет.Разработка контейнеров, исключающих исключительные ситуации, при наличии распределителей, которые могут генерировать при копировании, перемещении, обмене или сравнении, практически невозможна.На практике распределитель не может содержать намного больше, чем указатель на некоторый ресурс, поэтому разрешение распределителям выдавать копии и т. Д. Добавит много боли практически без выгоды.

...