2014-10-01 4 views
14

Ja przeglądając stronę cppreference na konstruktorów kopiowanie tutaj: http://en.cppreference.com/w/cpp/language/copy_constructorCzym jest rozróżnienie między konstruktorami kopii domyślnie deklarowanymi i niejawnie zdefiniowanymi?

Czytałem 2 sekcje dotyczące niejawnie-zadeklarowane konstruktorów kopiowania i niejawnie zdefiniowane konstruktorów kopiowania dość kilka razy, ale nadal nie rozumiem różnica. Czy domyślnie deklarowany, ale NIE zdefiniowany konstruktor może powodować problemy z linkerem?

Zasady są bardzo złożone. Nie pamiętam, żeby w C++ 03 istniało rozróżnienie: albo masz konstruktor kopiowania generowany przez kompilator, albo nie.

Czy ktoś może wyjaśnić (w prostszych słowach), jakie są różnice/różnice między tymi dwiema kategoriami?

Odpowiedz

11

Jest to wyjaśnione w raporcie w normie na początku klauzuli 12:

[Uwaga: Realizacja niejawnie deklarować te funkcje składowe dla niektórych typów klasowych, gdy program nie nie jawnie je zadeklaruj. Wdrożenie domyślnie je zdefiniuje, jeśli zostaną wykorzystane odr (3.2). Patrz 12.1, 12.4 i 12.8. - koniec uwaga]

Normy odniesienia dla C++ 14 (N3936) to 12.1/5 12,4/6, 12,8/13 12,8/26.W każdym przypadku odpowiednia funkcja specjalnego członka jest niejawnie zdefiniowana, jeśli jest domyślnie zdefiniowana i nie jest zdefiniowana jako usunięta, i albo jest używana odr lub jest jawnie domyślna. Jeśli mamy coś podobnego

struct Foo {}; 

i żadnych obiektów typu Foo kiedykolwiek stworzone, wszystkie sześć specjalnych funkcji składowych (domyślny konstruktor, destruktor, kopia konstruktora, przesuń konstruktora, skopiuj operator przypisania, przesuń operatora przypisania) są niejawnie zadeklarowana jako domyślne, ale nieokreślone, ponieważ nie są używane odr.

+1

Bardzo niesamowite wytłumaczenie. Chciałbym zobaczyć więcej przykładów różnych scenariuszy, które łączą deklarację niejawną z innymi sytuacjami usuniętymi/domyślnie zdefiniowanymi/trywialnymi. –

3

Jeśli istnieje domyślnie określony konstruktor kopii, jest zawsze zdefiniowany jako . Opcje dla swojej definicji są:

  • usunięte
  • trywialny
  • niejawnie zdefiniowane

Jeśli program próbuje użyć konstruktora, który jest zdefiniowany jako usunięte następnie program jest źle sformułowane (tzn. pojawi się błąd kompilatora). W pozostałych przypadkach wywoływana jest funkcja.

Strona, którą link opisuje, w których sytuacjach występuje każda z trzech powyższych opcji.

C++ 11 dodał pojęcie d funkcji delete, ponieważ gdy chcesz jawnie uczynić klasę nie można jej kopiować (itp). Zdefiniujesz jego konstruktora kopiowania jako usunięty, a następnie kompilator wygeneruje błąd, jeśli ktoś spróbuje skopiować twój obiekt.

Rozróżnienie między , które można trywialnie kopiować i nie można go kopiować w trywialny sposób, zawsze istniało, ale nie było to wyraźnie powiedziane; Wywnioskowałeś z reguł dotyczących POD, w których sytuacjach wolno było używać memcpy do kopiowania obiektów.

Jak Brian zwraca uwagę, że jest bardziej dokładne, aby powiedzieć, że jest zdefiniowana w razie potrzeby. Kompilator nigdy nie deklaruje domyślnie funkcji, a następnie generuje błąd łącza. Ale jeśli definicja funkcji nie jest wymagana do pomyślnego zbudowania pliku wykonywalnego, nie będzie zawracać sobie głowy tworzeniem definicji.

+0

Może jestem źle poinformowany, ale deklaracje są podzbiorem definicji. Innymi słowy, jeśli coś jest zdefiniowane, jest również zadeklarowane. Jednakże, jeśli coś jest zadeklarowane, co nie oznacza, że ​​jest zdefiniowane (tak byśmy powiedzieli, że zostało zdefiniowane) –

+1

@ void.pointer Mówisz o konstruktach składni podanych przez użytkownika. Mówi się o konstruktorach generowanych przez kompilator. Kompilator nigdy nie deklaruje funkcji bez zdefiniowania jej (no cóż - jak wskazuje Brian, kompilator nie będzie zawracał sobie głowy generowaniem definicji, jeśli nigdy nie zostanie wywołana). –