2015-11-27 9 views
24

Zainspirowany postem Why does destructor disable generation of implicit move methods?, zastanawiałem się, czy to samo dotyczy domyślnego destruktora wirtualnego, np.Czy domyślny destruktor wirtualny uniemożliwia wykonywanie operacji przenoszenia generowanych przez kompilator?

class WidgetBase // Base class of all widgets 
{ 
    public: 
     virtual ~WidgetBase() = default; 
     // ... 
}; 

jako klasa ma być klasą bazową hierarchii widget muszę zdefiniować swój wirtualny destruktor, aby uniknąć wycieków pamięci i niezdefiniowane zachowanie podczas pracy ze wskaźnikami klasy bazowej. Z drugiej strony nie chcę uniemożliwić kompilatorowi automatycznego generowania operacji przenoszenia.

Czy domyślny destruktor wirtualny uniemożliwia operacje przenoszenia generowane przez kompilator?

Odpowiedz

21

Tak, zadeklarowanie dowolnego destruktora zapobiegnie domyślnej deklaracji konstruktora ruchu.

N3337 [class.copy]/9: Jeżeli definicja klasy X nie jawnie zadeklarować konstruktor poruszać, jeden będzie niejawnie zadeklarowana jako domyślnie wtedy i tylko wtedy, gdy

  • X nie posiada konstruktor kopiujący użytkownika zadeklarowane ,
  • X nie posiada operatorowi przypisanie kopii użytkownika uznane,
  • X nie posiada operatorowi przypisanie ruch użytkownika uznane,
  • X nie ma zadeklarowanego przez użytkownika destruktora i
  • Konstruktor ruchu nie zostanie niejawnie zdefiniowany jako usunięty.

Deklarowanie destruktora i definiując go jako default liczy się jako użytkownik-oświadczył.

Musisz zadeklarować konstruktor ruch i zdefiniować go jako default siebie:

WidgetBase(WidgetBase&&) = default; 

Zauważ, że to z kolei określić konstruktor kopiujący jak delete, więc trzeba default że One Too :

WidgetBase(const WidgetBase&) = default; 

zasady kopiowania i przenoszenia operatory przypisania są bardzo podobne, tak więc będziesz musiał default je, jeśli chcesz je.

Powiązane problemy