2017-12-27 139 views
8

Poniższy kod jest dobrze opracowana:Korzystanie = default w rozumieniu = usuń

struct B { 
    B(int) {} 
}; 

struct D : B { 
    D() = default; 
}; 

Aż muszę utworzyć instancję klasy D:

D d; // error: use of deleted function 'D::D()' 

Czy jest jakiś powód (przypadek użycia) zezwalać na = default dla konstruktora D, kiedy to faktycznie działa jako = delete;?

+0

Jeśli zmienisz B, D automatycznie zrobi to, co trzeba. –

+0

Jakiego kompilatora używasz?Czy to możliwe, ponieważ twoja struktura jest pusta i nic nie robi, stąd kompilator pomija ją w całości zgodnie z definicją '= default'? –

+1

g ++ 5.1.0 'uwaga: 'D :: D()' jest niejawnie usunięty, ponieważ domyślna definicja byłaby źle sformułowana:' i 'błąd: brak pasującej funkcji dla wywołania 'B :: B()'' –

Odpowiedz

11

g++ daje ładny wyjaśnienie błędu:

bla.cpp:6:5: note: ‘D::D()’ is implicitly deleted because the default definition would be ill-formed: D() = default;

Domyślny konstruktor będzie próbował skonstruować wszystkie części D. Nie masz żadnych pól, ale ma on początkową wartość B - która nie ma pustego konstruktora, a tylko jeden: int.

Domyślne zachowanie ma sens - D nie powinien mieć pustego konstruktora, chyba że wyraźnie stwierdzono, który int skonstruować B z, a kompilator nie chce zgadywać. W przeciwnym razie będziesz mieć obiekt D iw zależności od tego, co stanie się w konstruktorze B może zawierać śmieci, na przykład podczas inicjowania pola.

Nie jestem pewien, czy chodziło o pytanie dosłownie jeśli zapytać, dlaczego jest to „dozwolone”, jak B domyślny konstruktor zostanie usunięty, ale myślę, że z dwóch powodów:

  1. Ten zachowanie jest dobrze zdefiniowane i nie ma powodu, aby go odrzucać. Wykrywanie błędu tylko wtedy, gdy próbujesz coś nielegalnie skonstruować, i tak jest zrobione.
  2. Jest bardziej elastyczny - zmiana B na domyślny konstruktor automatycznie zezwala na D.
6

Is there any reason (use case) to allow = default for D's constructor, when it's actually works as = delete;?

To nie działa jak =delete. Mówi dokładnie, co ma powiedzieć. Że wyraźnie chcesz, aby kompilator wygenerował domyślną implementację.

Tak się składa, że ​​wygenerowany kompilator musi zostać zdefiniowany jako usunięty. Ponieważ domyślny konstruktor B jest niejawnie usunięty.

+0

Wiem, że '= delete' nie jest' = default', ale czy w moim przypadku particalar istnieje pewna różnica? Jestem całkiem pewien, że nic nie zmieniło się semantycznie, jeśli zmienię '= default' na' = delete'. Czy się mylę? – alexolut

+2

@alexolut - Funkcja jest usuwana w dowolny sposób. Przyczyna jest inna. Jeśli w przyszłości 'B' otrzyma domyślny c'tor, to również" D ". Jeśli spłaszczysz się, usuń go, nie będzie. Niektórzy twierdzą, że jest to znaczna różnica semantyczna. – StoryTeller

1

B ma inny niż domyślny konstruktor (jego konstruktor przyjmuje argument, który nie ma wartości domyślnej).

Pochodna D klasa zatem nie ma domyślnego konstruktora, jego domyślny konstruktor zostanie usunięty (jak kompilator nie może generować konstruktor D które mogą wywołać konstruktor tej klasy dominującej B(int).)

D() = default; po prostu mówi, że chcesz domyślny konstruktor dla D i jak opisano powyżej, domyślny konstruktor jest usuwany.