Ошибка с оператором копирования/присваивания для класса, который имеет переменную std:: atomic member
У меня есть класс, как показано ниже.
#include <atomic>
static const long myValue = 0;
class Sequence
{
public:
Sequence(long initial_value = myValue) : value_(initial_value) {}
private:
std::atomic<long> value_;
};
int main()
{
Sequence firstSequence;
Sequence secondSequence = firstSequence;
return 0;
}
Я получаю ошибку компиляции, подобную этой,
test.cpp:21:36: error: use of deleted function ‘Sequence::Sequence(const Sequence&)’
test.cpp:5:7: error: ‘Sequence::Sequence(const Sequence&)’ is implicitly deleted because the default definition would be ill-formed:
test.cpp:5:7: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’
Это то, что конструктор копирования по умолчанию и операнд присваивания не работают в этом случае?
PS: Я использую gcc версии 4.6.3
Ответы
Ответ 1
Вы не можете копировать атоматику со стандартным конструктором копирования, так как все загрузки и магазины должны выполняться явно. Вам нужно написать собственный конструктор копирования для Sequence
, который выполняет некоторую инициализацию формы value_(rhs.value_.load())
(возможно, с более расслабленным порядком памяти).
Ответ 2
Atomic удалил copy-ctor. Поэтому copy/move-ctors в вашем классе удаляются.
n3337 12,8/11
Неявно объявленный конструктор copy/move является встроенным публичным членом своего класса. По умолчанию копия /
move для класса X определяется как удаленный (8.4.3), если X имеет:
- нестатический элемент данных класса M (или его массив), который нельзя скопировать/переместить, потому что
(13.3), применительно к соответствующему конструктору Ms, приводит к двусмысленности или
функция, которая удалена или недоступна для конструктора по умолчанию,
Ответ 3
Поскольку нет функции std::atomic<long int>::atomic(const std::atomic<long int>&)
, компилятор не может создать конструктор копии по умолчанию для класса Sequence
. Если вам нужен конструктор копирования для этого класса (и если вы хотите, чтобы Sequence secondSequence = firstSequence;
работал), вам нужно написать его.
Это требование требуется по стандарту:
Ниже приведены атомный интеграл и типы адресов. Эти типы должны иметь стандартную компоновку. Они должны иметь тривиальный конструктор по умолчанию, конструктор конструктивных конструкторов constexpr, конструктор удаленной копии, оператор делегирования удаленной копии и тривиальный деструктор. Эти типы должны поддерживать агрегатный синтаксис инициализации.
Ответ 4
Я бы предположил, что выбор для удаления конструктора копирования в стандарте был по двум причинам:
-
требуется пара загрузки/хранения. Есть ли способ обеспечить, чтобы это было сделано, если вы не контролируете вызывающих пользователей std:: atomic?
-
Что вы делаете, если тип std:: atomic < > , который вы использовали, был тем, для которого is_lock_free() является false (т.е. в реализации для этого типа целочисленного размера требуется мьютекс)? Какую семантику копирования вы используете для инициализации мьютекса? Мьютекс, который неявно скопирован, нуждается в повторной инициализации, поскольку он может быть несчастлив скопирован в заблокированном состоянии. Я предполагаю, что std:: mutex также имеет конструктор удаленной копии из-за этого, и это также вызывает требование в std:: atomic.