Можно ли использовать некопируемый элемент в качестве альтернативы, чтобы сделать объект некопируемым?

Говорят, что класс с некопируемым членом также не копируется. Из SO, чтобы сделать класс некопируемым, есть следующие варианты:

  1. Используйте boost:: noncopyable
  2. Объявите конструктор и оператор присваивания закрытыми.
  3. Удалить конструктор копирования.

    class foo 
    {
        private:
          std::mutex _dummy;
    };
    

Вопрос: Будет ли включение фиктивного некопируемого элемента использоваться для аналогичных целей и для простоты? Каковы минусы?


person ark1974    schedule 29.09.2018    source источник
comment
Вы отметили этот вопрос C++11. Есть ли какая-то причина, по которой вы не можете просто = delete скопировать конструктор?   -  person Nicol Bolas    schedule 29.09.2018
comment
@NicolBolas: Спасибо, я добавил это.   -  person ark1974    schedule 29.09.2018
comment
Будет ли включение фиктивного некопируемого элемента использоваться для той же цели и для простоты? Каковы минусы? - Нет, недостаточно. Вы можете написать конструктор копирования, который ничего с этим не сделает.   -  person max66    schedule 29.09.2018
comment
Всегда говорите, что вы имеете в виду - добавление некопируемого объекта (особенно чего-то вроде мьютекса) просто запутывает ваш код. Просто удалите конструктор копирования и, возможно, оператор присваивания.   -  person    schedule 29.09.2018
comment
@max66 Да, достаточно, просто нежелательно.   -  person    schedule 29.09.2018
comment
@NeilButterworth - Может быть, я должен сказать, что этого недостаточно ... Я имею в виду: можно написать класс с некопируемым элементом и конструктором копирования, который не копирует его значение. Таким образом, объект является копируемым и содержит некопируемый элемент. Я знаю: глупо. По той же причине сделать конструктор копирования и operator=() private недостаточно, потому что вы можете сделать функцию friend для класса, и класс станет копируемым (внутри функции friend).   -  person max66    schedule 29.09.2018


Ответы (1)


Начиная с C++11, правильной идиомой для того, чтобы сделать класс некопируемым, является = delete конструктор копирования/оператор присваивания. Это то, что говорят программистам на С++, и это то, что другие программисты на С++ ожидают увидеть, когда ищут такое поведение в вашем классе.

Хорошо иметь подобъект (член или базовый класс), который нельзя копировать, и поэтому ваш конструктор копирования/оператор присваивания по умолчанию будет неявно удален. Но вы должны делать это только для подобъекта, который оказывается некопируемым. То есть у вас есть unique_ptr<T> или mutex или что-то еще в качестве члена, потому что вам нужен unique_ptr<T> или mutex в качестве данных экземпляра класса. Не потому, что вы используете его как хак, чтобы сделать тип некопируемым.

Недостатки использования подобъекта-члена для этой цели:

  1. Это путает смысл вашего кода. Ваш пример mutex _dummy; говорит мне, что в вашем типе есть mutex. Если ничто никогда не использует эту переменную, это говорит мне о том, что ваш код довольно бессвязен; если вам не нужен подобъект, вы его не объявляете. = delete - это правильная идиома, поэтому вы должны использовать ее.

  2. boost::noncopyable был идиомой C++98/03, потому что это был пустой класс. Таким образом, обычная пустая базовая оптимизация гарантирует, что она не будет занимать место в производном классе. Пустые члены не получают такой оптимизации, поэтому член boost::noncopyable всегда будет увеличивать ваш класс без каких-либо преимуществ. И хотя вы могли бы указать на предстоящий атрибут C++20 [[no_unique_address]], см. причину № 1.

person Nicol Bolas    schedule 29.09.2018