В чем разница между объявлением конструктора private и = delete?

Например, я хочу объявить класс, но хочу, чтобы клиент не мог использовать конструктор копирования (или оператор назначения копирования)

Оба из следующих двух не позволяют использовать конструктор копирования:

1.

class Track
{
public:
Track(){};
~Track(){};
private:
Track(const Track&){};
};

2.

class Track
{
public:
Track(){};
~Track(){};
Track(const Track&)=delete;
};

Является ли один из этих способов «более правильным», чем другой, или равны? Есть ли побочный эффект?

//Does not compile with both the above ways
int main()
{
Track l;
Track p(l);
}

16

Решение

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

= delete удалений конструктор Он не генерируется компилятором и просто не будет существовать.

Так что, скорее всего, = delete это то, что вы хотите. (хотя с оговоркой, что не все компиляторы поддерживают этот синтаксис, так что, если переносимость является проблемой …)

15

Другие решения

Объявление конструктора копирования private по-прежнему позволяет функции-члены Track класс для копирования-создания экземпляров этого класса, в то время как удаление его просто запрещает копирование этого объекта.

В C ++ 11 удаление конструктора копирования — это верный способ выразить тот факт, что класс не подлежит копированию (если, конечно, не имеет смысла позволять функциям-членам Trackили друзья Trackскопировать-построить Track объекты).

7

Создание частного конструктора было в основном «взломом» в старом C ++, поскольку это был единственный способ запретить пользователям использовать их. Способность к delete специальные функции-члены были введены только в C ++ 11, и это лучший и более идиоматический способ сказать, что класс не может быть скопирован. так как это явно о намерение.

Частные конструкторы имеют другое использование, кроме полного запрещения их использования (например, они могут вызываться статическими функциями-членами класса). Таким образом, простое создание конструктора не очень хорошо передает намерение, и получающаяся ошибка также не очень ясна.

5

Ваше первое решение сообщает читателю, что конструктор копирования является частным и не должен использоваться.
Ваше второе решение действительно только в C ++ 11. Из-за этого я бы сказал, что более портативная и удобочитаемая реализация будет вашей первой, используя private-свойство.

0

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

Во втором случае синтаксис запрещает копирование. Это родной C ++.

Основное отличие программиста — читаемость и понимание кода. Первый случай является избыточным, зачем объявлять конструктор копирования, делать его закрытым и не реализовывать его. Клиент должен многое сделать здесь.

Вы можете просто использовать «= delete» и четко указать, что вы пытаетесь сделать.

0

Ваш первый подход не мешает самому классу копировать себя. Традиционный способ решить эту проблему — объявить конструктор копирования закрытым. а также оставить это невыполненным.

Проблема с этим, однако, заключается в том, что намерение не может быть очевидным. Кто-то, читающий код, может не понять, почему существует осиротевшее объявление, и может ошибочно удалить его. Комментарии могут помочь, как бы унаследовав от boost::noncopyable если Boost доступен для вас.

Второй подход делает намерение очевидным и это то, что вы должны предпочесть, если вы можете использовать C ++ 11.

0

Если вы на C ++ 11, используйте delete, Причина в том, что он делает вызов явным, а цель — ясной. Вы все еще можете случайно использовать приватный конструктор (например, в ограниченном наборе областей), но компилятор запретит вам использовать удаленный конструктор.

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

Если ваши необходимые наборы инструментов не поддерживают удаленные конструкторы (= delete), вы не должны определять это (как видно из вашего вопроса) — только объявлять и оставьте это неопределенным, например: private: \n Track(const Track&);

0
По вопросам рекламы [email protected]