Standardkonstruktor mit leeren Klammern

Lesezeit: 5 Minuten

Standardkonstruktor mit leeren Klammern
Martin Beckett

Gibt es einen guten Grund dafür, dass ein leerer Satz runder Klammern (Klammern) für den Aufruf des Standardkonstruktors in C++ nicht gültig ist?

MyObject  object;  // ok - default ctor
MyObject  object(blah); // ok

MyObject  object();  // error

Ich scheine jedes Mal automatisch “()” einzugeben. Gibt es einen guten Grund, warum das nicht erlaubt ist?

  • Jemand sollte sich einen besseren Titel dafür einfallen lassen, aber ich kann mir nicht vorstellen, was das wäre. Buchstabieren Sie zumindest “Konstruktor”, um die Suchmaschine(n) zu unterstützen.

    – Adam Mitz

    8. Oktober 2008 um 5:18 Uhr

  • Und dies ist nur ein weiteres gutes Beispiel dafür, dass C++ kontextsensitiv ist. Der Beispielcode in der Frage würde auch fehlschlagen, wenn blah wäre eine Klasse.

    – Albert

    27. August 2010 um 21:03 Uhr

  • Eine Sache, die mir aufgefallen ist, ist, dass der Compiler keinen Fehler ausgibt, wenn ich nur den Standardkonstruktor habe, wenn ich ihn verwende () z.B MyObject object funktioniert wie gewohnt & MyObject object() gibt keinen Fehler! Könnte bitte jemand erklären warum? Ich meine, ich habe die Funktion in meinem nicht definiert main… also sollte es einen Fehler geben, oder? Vielen Dank im Voraus!

    – Mailand

    12. November 2020 um 0:04 Uhr

Standardkonstruktor mit leeren Klammern
Konstantin

Die ärgerlichste Analyse

Dies hängt mit dem zusammen, was als “der ärgerlichste Parse von C++” bekannt ist. Grundsätzlich wird alles, was vom Compiler als Funktionsdeklaration interpretiert werden kann, als Funktionsdeklaration interpretiert.

Ein weiterer Fall des gleichen Problems:

std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());

v wird als Funktionsdeklaration mit 2 Parametern interpretiert.

Die Problemumgehung besteht darin, ein weiteres Paar Klammern hinzuzufügen:

std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());

Oder, wenn Sie C++11 und Listeninitialisierung (auch bekannt als einheitliche Initialisierung) zur Verfügung haben:

std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};

Damit kann es auf keinen Fall als Funktionsdeklaration interpretiert werden.

  • Nitpick: du kann Deklarieren Sie Funktionen innerhalb von Funktionen. Es heißt lokale Funktionen in C, und mindestens extern "C" foo();-style ist auch in C++ erlaubt.

    – Marc Mutz – mmutz

    8. August 2009 um 10:20 Uhr

  • Wie kann man das als Funktion interpretieren?

    – Casebash

    29. Oktober 2010 um 1:00 Uhr

  • @Casebash, std::vector ist Rückgabetyp; v ist Funktionsname; ( öffnet formale Argumentliste; std::istream_iterator ist der Typ des ersten Arguments; ifs ist der Name des ersten Arguments, () um herum ifs effektiv ignoriert werden; Sekunde std::istream_iterator ist der Typ des zweiten Arguments, das unbenannt ist, () um ihn herum werden ebenfalls ignoriert; ‘);’ schließt Argumentliste und Funktionsdeklaration.

    – Konstantin

    30. Oktober 2010 um 7:31 Uhr


  • Es gibt eine Mehrdeutigkeit in der Grammatik, die Ausdrucksanweisungen und Deklarationen betrifft: Eine Ausdrucksanweisung mit einer expliziten Typumwandlung im Funktionsstil als Teilausdruck ganz links kann von einer Deklaration nicht zu unterscheiden sein, bei der der erste Deklarator mit einem ( beginnt. In diesen Fällen wird die Anweisung ist eine Deklaration (C++ ISO/IEC (2003) 6.8.1).

    – bartolo-otrit

    28. September 2012 um 9:12 Uhr

  • @Constantin, die Klammern nach dem zweiten Argument werden nicht ignoriert. Der zweite Parameter ist kein a std::istream_iterator sondern ein Zeiger/Verweis auf eine Funktion, die keine Argumente akzeptiert und eine zurückgibt istream_iterator.

    – CTMacUser

    15. Februar 2014 um 0:25 Uhr

1647298208 441 Standardkonstruktor mit leeren Klammern
1800 INFORMATIONEN

Weil es als Deklaration für eine Funktion behandelt wird:

int MyFunction(); // clearly a function
MyObject object(); // also a function declaration

  • Aber es sollte einen Fehler geben, oder? Weil wir die nicht definiert haben object() funktion richtig? Könnten Sie das bitte näher erläutern? Ich bin gerade verwirrt. Vielen Dank im Voraus!

    – Mailand

    12. November 2020 um 0:07 Uhr

  • Nebenbei bemerkt, in meiner mainich habe sogar diese ausprobiert: any_variable_name random_function_name() z.B int func1() , double func2(), void func3(), usw. und alle funktionieren, dh mein Programm wird ohne Fehler kompiliert! Allerdings habe ich keine dieser Funktionen definiert, also sollte ich Fehler bekommen, richtig?

    – Mailand

    12. November 2020 um 0:13 Uhr


  • @Milan Ich würde Linker-Fehler erwarten, wenn Sie tatsächlich versuchen würden, diese Funktionen aufzurufen. Sonst sind es nur Erklärungen

    – 1800 INFORMATIONEN

    15. November 2020 um 22:31 Uhr

Die gleiche Syntax wird für die Funktionsdeklaration verwendet – zB die Funktion objectnimmt keine Parameter und kehrt zurück MyObject

  • Danke – es würde mir nicht einfallen, eine Funktion mitten in einem anderen Code zu deklarieren. Aber ich nehme an, es ist legal.

    – Martin Beckett

    7. Oktober 2008 um 20:36 Uhr

Weil der Compiler denkt, dass es sich um eine Deklaration einer Funktion handelt, die keine Argumente akzeptiert und eine MyObject-Instanz zurückgibt.

Sie können auch die ausführlichere Konstruktionsweise verwenden:

MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);

In C++0x ermöglicht dies auch auto:

auto object1 = MyObject();
auto object2 = MyObject(object1);

  • Dies erfordert einen Kopierkonstruktor und ist ineffizient

    – Casebash

    29. Oktober 2010 um 1:01 Uhr


  • @Casebash: Der Compiler ist wahrscheinlich schlau genug, um einige zu verwenden RVO-ähnliche Optimierung verhindern, dass es ineffizient ist.

    – dalle

    29. Oktober 2010 um 11:23 Uhr

  • „Wahrscheinlich“ bedeutet „ich vermute“. Bei der Optimierung will man meist nicht raten, sondern den expliziten Weg gehen.

    – Stefan

    4. November 2014 um 14:35 Uhr

  • @Stefan: Du musst nicht “raten”; Copy Elision wird hier in allen Mainstream-Compilern vorkommen, und das ist seit weit über einem Jahrzehnt der Fall. Nicht, dass dies ein guter Code wäre.

    – Leichtigkeitsrennen im Orbit

    25. Juni 2015 um 18:19 Uhr


  • Da es in C++17 kein Kopieren/Verschieben gibt, ist das Verhalten als identisch mit der direkten Initialisierung definiert

    – MM

    22. Februar um 23:45 Uhr

1647298209 138 Standardkonstruktor mit leeren Klammern
Schwarz

Ich denke, der Compiler würde es nicht wissen, wenn diese Aussage:

MyObject-Objekt();

ist ein Konstruktoraufruf oder ein Funktionsprototyp, der eine benannte Funktion deklariert Objekt mit Rückgabetyp MeinObjekt und keine Parameter.

  • Dies erfordert einen Kopierkonstruktor und ist ineffizient

    – Casebash

    29. Oktober 2010 um 1:01 Uhr


  • @Casebash: Der Compiler ist wahrscheinlich schlau genug, um einige zu verwenden RVO-ähnliche Optimierung verhindern, dass es ineffizient ist.

    – dalle

    29. Oktober 2010 um 11:23 Uhr

  • „Wahrscheinlich“ bedeutet „ich vermute“. Bei der Optimierung will man meist nicht raten, sondern den expliziten Weg gehen.

    – Stefan

    4. November 2014 um 14:35 Uhr

  • @Stefan: Du musst nicht “raten”; Copy Elision wird hier in allen Mainstream-Compilern vorkommen, und das ist seit weit über einem Jahrzehnt der Fall. Nicht, dass dies ein guter Code wäre.

    – Leichtigkeitsrennen im Orbit

    25. Juni 2015 um 18:19 Uhr


  • Da es in C++17 kein Kopieren/Verschieben gibt, ist das Verhalten als identisch mit der direkten Initialisierung definiert

    – MM

    22. Februar um 23:45 Uhr

1647298209 706 Standardkonstruktor mit leeren Klammern
Michael Burr

Wie schon oft erwähnt, ist es eine Erklärung. Es ist so für die Abwärtskompatibilität. Einer der vielen Bereiche von C++, die aufgrund ihres Erbes doof/inkonsistent/schmerzhaft/gefälscht sind.

1003340cookie-checkStandardkonstruktor mit leeren Klammern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy