default Konstruktur vs Konstruktor mit leerem Rumpf
-
Hey Leute,
kurze Fragen, was ist der Unterschied zwischen dem default-Konstruktor für eine Klasse A und diesem hier
A() {}
welcher keine Parameter erwartet und einen leerem Rumpf vorweist?
Gruß
-
Nichts, außer dass du den Default Konstruktor explizit Definieren musst, wenn du noch andere Konstruktoren hast.
-
Die einzige Krümelkackerei die mir einfällt ist, dass der implizite Konstruktor nur bei Bedarf erzeugt wird, während für den ausgeschriebenen Konstruktor auf jeden Fall Code erzeugt wird (sofern dieser überhaupt etwas täte). Außerdem kann der ausgeschriebenen Konstruktor auch nicht-inline sein (in deinem Beispiel ist er es nicht, aber du hättest ihn ja auch außerhalb der Klasse definieren können), der implizite Konstruktor ist automatisch inline.
Die relevanteste Stelle im Standard:
C++11, 12.1,6 schrieb:
A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-
used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.
The implicitly-defined default constructor performs the set of initializations of the class that would be
performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty
compound-statement. If that user-written default constructor would be ill-formed, the program is ill-formed.
If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5),
the implicitly-defined default constructor is constexpr. Before the defaulted default constructor for a
class is implicitly defined, all the non-user-provided default constructors for its base classes and its non-
static data members shall have been implicitly defined. [ Note: An implicitly-declared default constructor
has an exception-specification (15.4). An explicitly-defaulted definition might have an implicit exception-
specification, see 8.4. — end note ]Hervorhebung durch mich.
Allgemein darfst du leere Konstruktoren und Destruktoren als Cargo-Cult von Leuten mit schlechten Lehrern ansehen. Schlimm wird's erst, wenn sie ihre Kopierkonstrukotren und Zuweisungsoperatoren auch leer implementieren. Ist hier im Forum schon oft genug vorgekommen.
-
Ein Default-Konstruktor ist das, was man ohne Parameter aufrufen kann.
Mit einem "leer" implementierten Konstruktor hat das nix zu tun.Und IIRC gibt es auch einen Unterschied zwischen einem "implicitly defined" Konstruktor und einem den man selbst mit {} "leer" definiert:
Der "implicitly defined" Konstruktor kann "trivial" sein (std::is_trivially_default_constructible
), der selbst mit {} definierte - soweit ich weiss - nicht.
(Ein mit "= default" definierter kann dagegen wieder "trivial" sein)
-
hustbaer schrieb:
Und IIRC gibt es auch einen Unterschied zwischen einem "implicitly defined" Konstruktor und einem den man selbst mit {} "leer" definiert:
Der "implicitly defined" Konstruktor kann "trivial" sein (std::is_trivially_default_constructible
), der selbst mit {} definierte - soweit ich weiss - nicht.
(Ein mit "= default" definierter kann dagegen wieder "trivial" sein)Stimmt, wichtiger Unterschied. Steht im Standard direkt über dem von mir zitierten Absatz.
-
hustbaer schrieb:
std::is_trivially_default_constructible
Daran hatte ich in der Tat nicht gedacht.
-
Was ist denn ein 'trivialer Konstruktor'?
-
Jockelx schrieb:
Was ist denn ein 'trivialer Konstruktor'?
Technisch darfst du dir darunter einen Konstruktor vorstellen, der einfach gar nix macht, zu dem also gar kein Maschinencode erstellt wird.
Im Standard ist dieser Begriff wichtig, weil sich damit Klassen in bestimmte Kategorien einteilen lassen, die unterschiedliche Stufen von Optimierung erlauben. Beispielsweise können POD-Klassen (= plain old data), wofür ein trivialer Konstruktor Voraussetzung ist, so behandelt werden wie C-Datentypen, also ohne dass man sich um Konstruktoren, Destruktoren oder Zuweisungsoperatoren kümmern muss, was z.B. erlaubt, diese mit memcpy (anstatt einzeln) zu kopieren.
Ein trivialer Konstruktor ist ein Konstruktor ist ein Konstruktor, der nicht vom Benutzer implementiert wurde (oder in C++11 deleted wurde) und für den gilt:
- Die Klasse hat keine virtuellen Funktionen oder virtuelle Basisklassen
- Kein (nichtstatischer) Klassenmember hat eine Initialisierung im Klassenrumpf
- Alle direkten Basisklassen haben triviale Konstruktoren
- Die Konstruktoren aller (nichtstatischen) Member sind ebenfalls trivial
(Frei übersetzt nach C++-Standard)
-
Dankeschön, SeppJ!