Значение = удалить после объявления функции - PullRequest
217 голосов
/ 01 апреля 2011
class my_class
{
    ...
    my_class(my_class const &) = delete;
    ...
};

Что означает = delete в этом контексте?

Существуют ли другие "модификаторы" (кроме = 0 и = delete)?

Ответы [ 9 ]

180 голосов
/ 01 апреля 2011

Удаление функции: функция C ++ 11 :

Общая идиома «запрет копирования» теперь может быть выражена непосредственно:

class X {
    // ...
    X& operator=(const X&) = delete;  // Disallow copying
    X(const X&) = delete;
};

[...]

Механизм «удаления» можно использовать для любой функции.Например, мы можем устранить нежелательное преобразование следующим образом:

struct Z {
    // ...

    Z(long long);     // can initialize with an long long         
    Z(long) = delete; // but not anything less
};
75 голосов
/ 01 апреля 2011
  1. = 0 означает, что функция является чисто виртуальной, и вы не можете создать экземпляр объекта из этого класса.Вы должны извлечь из него и реализовать этот метод
  2. = delete означает, что компилятор не будет генерировать эти конструкторы для вас.AFAIK это разрешено только в конструкторе копирования и операторе присваивания.Но я не слишком хорош в грядущем стандарте.
19 голосов
/ 17 августа 2017

Этот отрывок из В языке программирования C ++ [4-е издание] - Бьярн Страуструп рассказывает о реальном назначении , стоящем за использованием =delete:

Использование копирования или перемещения по умолчанию для класса в иерархии обычно катастрофа : учитывая только указатель на базу, мы просто не знаем, что члены производного класса (§3.2.2), поэтому мы не можем знать, как копировать их . Поэтому лучше всего обычно удалить копию по умолчанию. и операции перемещения, то есть, чтобы устранить определения по умолчанию эти две операции:

class Shape {
public:
  Shape(const Shape&) =delete; // no copy operations
  Shape& operator=(const Shape&) =delete;

  Shape(Shape&&) =delete; // no move operations
  Shape& operator=(Shape&&) =delete;
  ˜Shape();
    // ...
};

Теперь попытка скопировать Shape будет поймана компилятором.

Механизм =delete является общим, то есть его можно использовать для подавления любой операции

7 голосов
/ 30 апреля 2018

Существуют ли другие "модификаторы" (кроме = 0 и = delete)?

Поскольку, похоже, никто не ответил на этот вопрос, я должен упомянуть, что естьтакже =default.

https://docs.microsoft.com/en-us/cpp/cpp/explicitly-defaulted-and-deleted-functions#explicitly-defaulted-functions

3 голосов
/ 15 мая 2018

Стандарты кодирования, с которыми я работал, содержали следующее для большинства объявлений классов:

//  coding standard: disallow when not used
T(void)                  = delete; // default ctor    (1)
~T(void)                 = delete; // default dtor    (2)
T(const T&)              = delete; // copy ctor       (3)
T(const T&&)             = delete; // move ctor       (4)
T& operator= (const T&)  = delete; // copy assignment (5)
T& operator= (const T&&) = delete; // move assignment (6)

Если вы используете любой из этих 6, вы просто закомментируете соответствующую строку.

Пример: класс FizzBus требует только dtor и, следовательно, не использует другие 5.

//  coding standard: disallow when not used
FizzBuzz(void)                         = delete; // default ctor (1)
// ~FizzBuzz(void);                              // dtor         (2)
FizzBuzz(const FizzBuzz&)              = delete; // copy ctor    (3)
FizzBuzz& operator= (const FizzBuzz&)  = delete; // copy assig   (4)
FizzBuzz(const FizzBuzz&&)             = delete; // move ctor    (5)
FizzBuzz& operator= (const FizzBuzz&&) = delete; // move assign  (6)

Мы закомментируем только 1 здесь и установим реализацию его где-то еще (вероятно, гдестандарт кодирования предполагает).Другие 5 (из 6) запрещены с удалением.

Вы также можете использовать '= delete', чтобы запретить неявные рекламные акции разных размеров ... пример

// disallow implicit promotions 
template <class T> operator T(void)              = delete;
template <class T> Vuint64& operator=  (const T) = delete;
template <class T> Vuint64& operator|= (const T) = delete;
template <class T> Vuint64& operator&= (const T) = delete;
3 голосов
/ 18 января 2017

= delete - это функция, представленная в C ++ 11. Согласно =delete не разрешается вызывать эту функцию.

Подробно.

Допустим, в классе.

Class ABC{
 Int d;
 Public:
  ABC& operator= (const ABC& obj) =delete
  {

  }
};

При вызове этой функции для назначения объекта она не разрешается. Средство назначения оператора собирается ограничить копирование из одного объекта в другой.

2 голосов
/ 01 апреля 2011

Новый стандарт C ++ 0x.Смотрите раздел 8.4.3 в N3242 рабочем проекте

0 голосов
/ 24 мая 2019

Удаленная функция неявно встроена

(Приложение к существующим ответам)

... И удаленная функция должна быть первым объявлением функции (кромедля удаления явных специализаций шаблонов функций - удаление должно быть при первом объявлении специализации), то есть вы не можете объявить функцию, а затем удалить ее, скажем, при определении локально для единицы перевода.

Цитирование [dcl.fct.def.delete] / 4 :

Удаленная функция неявно встроена.( Примечание: Правило единого определения ( [basic.def.odr] ) применяется к удаленным определениям. - конечная заметка ] Удаленное определение функциидолжно быть первым объявлением функции или, для явной специализации шаблона функции, первым объявлением этой специализации. [Пример:

struct sometype {
  sometype();
};
sometype::sometype() = delete;      // ill-formed; not first declaration

- конец примера )

Основной шаблон функции с удаленным определением может быть специализированным

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

До концепции удаленных функций C ++11, можно было бы сделать это, просто опуская определение шаблона первичной функции, но это дало неясные неопределенные ссылки ошибки, которые, вероятно, не давали никакого семантического намерения от автора шаблона первичной функции (намеренно опущен?).Если вместо этого мы явно удалим шаблон первичной функции, сообщения об ошибках в случае, если не найдена подходящая явная специализация, станут намного приятнее, а также показывают, что пропуск / удаление определения шаблона первичной функции было преднамеренным.

#include <iostream>
#include <string>

template< typename T >
void use_only_explicit_specializations(T t);

template<>
void use_only_explicit_specializations<int>(int t) {
    std::cout << "int: " << t;
}

int main()
{
    const int num = 42;
    const std::string str = "foo";
    use_only_explicit_specializations(num);  // int: 42
    //use_only_explicit_specializations(str); // undefined reference to `void use_only_explicit_specializations< ...
}

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

#include <iostream>
#include <string>

template< typename T >
void use_only_explicit_specializations(T t) = delete;

template<>
void use_only_explicit_specializations<int>(int t) {
    std::cout << "int: " << t;
}

int main()
{
    const int num = 42;
    const std::string str = "foo";
    use_only_explicit_specializations(num);  // int: 42
    use_only_explicit_specializations(str);
    /* error: call to deleted function 'use_only_explicit_specializations' 
       note: candidate function [with T = std::__1::basic_string<char>] has 
       been explicitly deleted
       void use_only_explicit_specializations(T t) = delete; */
}

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

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

#include <cstdint>
#include <iostream>

void warning_at_best(int8_t num) { 
    std::cout << "I better use -Werror and -pedantic... " << +num << "\n";
}

template< typename T >
void only_for_signed(T t) = delete;

template<>
void only_for_signed<int8_t>(int8_t t) {
    std::cout << "UB safe! 1 byte, " << +t << "\n";
}

template<>
void only_for_signed<int16_t>(int16_t t) {
    std::cout << "UB safe! 2 bytes, " << +t << "\n";
}

int main()
{
    const int8_t a = 42;
    const uint8_t b = 255U;
    const int16_t c = 255;
    const float d = 200.F;

    warning_at_best(a); // 42
    warning_at_best(b); // implementation-defined behaviour, no diagnostic required
    warning_at_best(c); // narrowing, -Wconstant-conversion warning
    warning_at_best(d); // undefined behaviour!

    only_for_signed(a);
    only_for_signed(c);

    //only_for_signed(b);  
    /* error: call to deleted function 'only_for_signed' 
       note: candidate function [with T = unsigned char] 
             has been explicitly deleted
       void only_for_signed(T t) = delete; */

    //only_for_signed(d);
    /* error: call to deleted function 'only_for_signed' 
       note: candidate function [with T = float] 
             has been explicitly deleted
       void only_for_signed(T t) = delete; */
}
0 голосов
/ 01 апреля 2011

Это новая вещь в стандартах C ++ 0x, где вы можете удалить унаследованную функцию.

...