Was ist der Unterschied zwischen „typedef“ und „using“ in C++11?

Lesezeit: 9 Minuten

Was ist der Unterschied zwischen „typedef und „using in C11
Anspruch

Ich weiß, dass wir in C++11 jetzt verwenden können using Typ Alias ​​zu schreiben, wie typedefS:

typedef int MyInt;

Ist nach meinem Verständnis gleichbedeutend mit:

using MyInt = int;

Und diese neue Syntax entstand aus den Bemühungen, eine Möglichkeit zu haben, “Template Typedef” auszudrücken:

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

Aber gibt es bei den ersten beiden Nicht-Template-Beispielen weitere subtile Unterschiede im Standard? Zum Beispiel, typedefs machen Aliasing auf “schwache” Weise. Das heißt, es wird kein neuer Typ erstellt, sondern nur ein neuer Name (Konvertierungen sind zwischen diesen Namen implizit).

Ist es das gleiche mit using oder generiert es einen neuen Typ? Gibt es Unterschiede?

  • Ich persönlich bevorzuge die neue Syntax, weil sie der regulären Variablenzuweisung viel ähnlicher ist und die Lesbarkeit verbessert. Bevorzugen Sie zum Beispiel typedef void (&MyFunc)(int,int); oder using MyFunc = void(int,int); ?

    – Matthias M.

    25. Mai 2012 um 8:08 Uhr

  • Ich stimme voll und ganz zu, ich verwende jetzt nur noch die neue Syntax. Deshalb habe ich gefragt, um sicherzugehen, dass es wirklich keinen Unterschied gibt.

    – Anspruch

    25. Mai 2012 um 8:21 Uhr

  • @MatthieuM. die beiden sind übrigens unterschiedlich. Es sollte sein typedef void MyFunc(int,int); (was eigentlich gar nicht so schlecht aussieht), bzw using MyFunc = void(&)(int,int);

    – R.Martinho Fernandes

    25. Mai 2012 um 14:28 Uhr

  • @R.MartinhoFernandes warum brauchst du (&) in using MyFunc = void(&)(int,int); ? Bedeutet das MyFunc ist ein Verweis auf eine Funktion? Was ist, wenn Sie die weglassen &?

    – Reich

    15. Juli 2015 um 4:50 Uhr

  • Ja, es ist eine Funktionsreferenz. Es ist gleichbedeutend mit typedef void (&MyFunc)(int,int);. Wenn Sie die weglassen & es ist äquivalent zu typedef void MyFunc(int,int);

    – R.Martinho Fernandes

    15. Juli 2015 um 12:24 Uhr

Sie sind äquivalent, aus dem Standard (Hervorhebung von mir) (7.1.3.2):

Ein Typedef-Name kann auch durch eine Alias-Deklaration eingeleitet werden. Der Bezeichner nach dem Schlüsselwort using wird zu einem Typedef-Namen, und der optionale Attributbezeichner-seq nach dem Bezeichner gehört zu diesem Typedef-Namen. Es hat dieselbe Semantik, als ob es durch den typedef-Spezifizierer eingeführt worden wäre. Insbesondere definiert es keinen neuen Typ und erscheint nicht in der Typ-ID.

  • Aus der Antwort, using Schlüsselwort scheint eine Obermenge von zu sein typedef. Dann wird typdef in Zukunft entwertet werden?

    – iammilind

    25. Mai 2012 um 4:28 Uhr

  • Abwertung nicht Notwendig zeigen die Absicht zum Entfernen an – Es ist lediglich eine sehr starke Empfehlung, ein anderes Mittel zu bevorzugen.

    – Eiserner Retter

    20. April 2013 um 20:37 Uhr

  • Aber dann frage ich mich, warum sie es nicht einfach zugelassen haben, dass typedef mit Vorlagen erstellt wird. Ich erinnere mich, irgendwo gelesen zu haben, dass sie das eingeführt haben using Syntax gerade weil die typedef Semantik funktionierte nicht gut mit Vorlagen. Was dem irgendwie widerspricht using ist so definiert, dass es genau die gleiche Semantik hat.

    – Celtschk

    21. Juli 2013 um 9:44 Uhr

  • @celtschk: Der Grund wird im Vorschlag erwähnt n1489. Ein Vorlagenalias ist nicht ein Alias ​​für einen Typ, aber ein Alias ​​für eine Gruppe von Vorlagen. Um zu unterscheiden zwischen typedef die verspürten einen Bedarf an einer neuen Syntax. Denken Sie auch daran, dass sich die Frage des OP auf den Unterschied zwischen Nicht-Vorlagenversionen bezieht.

    – Jess Gut

    21. Juli 2013 um 22:19 Uhr

  • Warum also wurde diese Redundanz eingeführt? 2 Syntaxen für den gleichen Zweck. Und ich sehe nicht typdef jemals missbilligt.

    – Benoît

    29. April 2017 um 20:31 Uhr

Was ist der Unterschied zwischen „typedef und „using in C11
Zhongming Qu

Sie sind weitgehend gleich, außer dass:

Die Alias-Deklaration ist mit Templates kompatibel, die Typedef im C-Stil hingegen nicht.

  • Besonders angetan von der Einfachheit der Antwort und dem Hinweis auf den Ursprung des Schriftsatzes.

    – g24l

    12. November 2015 um 13:34 Uhr

  • @ g24l du meinst typedef … wahrscheinlich

    – März 2377

    14. September 2019 um 5:23 Uhr

  • Was ist der Unterschied zwischen C und C++ in typedef wenn ich fragen darf?

    – McSinyx

    16. Dezember 2019 um 11:03 Uhr

  • Dies beantwortet die Frage jedoch nicht. Ich kenne diesen Unterschied bereits und habe im ursprünglichen Beitrag darauf hingewiesen. Ich habe nur nach dem Fall gefragt, in dem Sie keine Vorlagen verwenden, ob es Unterschiede gibt.

    – Anspruch

    30. Juni 2020 um 22:36 Uhr

  • die Streichung des Wortes „weitgehend“ würde dies deutlicher machen

    – pm100

    30. Dezember 2021 um 1:42 Uhr

1647149413 697 Was ist der Unterschied zwischen „typedef und „using in C11
4xy

Die verwenden Syntax hat einen Vorteil, wenn sie innerhalb von Vorlagen verwendet wird. Wenn Sie die Typabstraktion benötigen, müssen aber auch Vorlagenparameter beibehalten werden, damit sie in Zukunft angegeben werden können. Du solltest so etwas schreiben.

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // to make it possible to substitue the whatever in future.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

Aber verwenden Syntax vereinfacht diesen Anwendungsfall.

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }

  • Ich habe aber bereits in der Frage darauf hingewiesen. Meine Frage lautet: Wenn Sie keine Vorlage verwenden, gibt es einen Unterschied zu Typedef. Wenn Sie zum Beispiel ‘Foo foo{init_value};’ Anstelle von ‘Foo foo(init_value)’ sollen beide dasselbe tun, aber nicht genau dieselben Regeln anwenden. Also habe ich mich gefragt, ob es einen ähnlichen versteckten Unterschied zu using/typedef gibt.

    – Anspruch

    2. Mai 2014 um 19:57 Uhr

1647149414 568 Was ist der Unterschied zwischen „typedef und „using in C11
dfrib

Alle nachstehenden Standardreferenzen beziehen sich auf N4659: März 2017 Post-Kona-Arbeitsentwurf/C++17 DIS.


Typedef-Deklarationen können dies, während Alias-Deklarationen dies nicht können(+)als Initialisierungsanweisungen verwendet werden

Aber gibt es bei den ersten beiden Nicht-Template-Beispielen weitere subtile Unterschiede im Standard?

  • Unterschiede in Semantik: keiner.
  • Unterschiede in zulässigen Kontexten: etwas(++).

(+) P2360R0 (Erweitern Sie die Init-Anweisung, um die Alias-Deklaration zuzulassen) wurde von CWG genehmigt und ab C++23 wurde diese Inkonsistenz zwischen Typedef-Deklarationen und Alias-Deklarationen entfernt.

(++) Zusätzlich zu den Beispielen von Alias-Vorlagenwas bereits im ursprünglichen Beitrag erwähnt wurde.

Gleiche Semantik

Wie geregelt durch [dcl.typedef]/2 [extract, emphasis mine]

[dcl.typedef]/2 EIN
typedef-name

kann auch durch ein eingeleitet werden
Alias-Deklaration. Die Kennung nach dem using Schlüsselwort wird zu a
typedef-name und das fakultative Attribut-Spezifizierer-Seq nach dem Kennung gehört dazu typedef-name. So ein
typedef-name hat dieselbe Semantik, als ob sie durch die eingeführt worden wäre typedef Bezeichner.
[…]

ein typedef-name eingeführt von einem Alias-Deklaration hat die gleiche Semantik als ob es von der eingeführt wurde typedef Erklärung.

Subtiler Unterschied in zulässigen Kontexten

Dies gilt jedoch nicht implizieren, dass die beiden Variationen die gleichen Einschränkungen in Bezug auf haben die Kontexte in denen sie verwendet werden dürfen. Und tatsächlich, wenn auch ein Eckfall, a typedef-Deklaration ist ein init-Anweisung und kann daher in Kontexten verwendet werden, die Initialisierungsanweisungen zulassen

// C++11 (C++03) (init. statement in for loop iteration statements).
for (typedef int Foo; Foo{} != 0;)
//   ^^^^^^^^^^^^^^^ init-statement
{
}

// C++17 (if and switch initialization statements).
if (typedef int Foo; true)
//  ^^^^^^^^^^^^^^^ init-statement
{
    (void)Foo{};
}

switch (typedef int Foo; 0)
//      ^^^^^^^^^^^^^^^ init-statement
{
    case 0: (void)Foo{};
}

// C++20 (range-based for loop initialization statements).
std::vector<int> v{1, 2, 3};
for (typedef int Foo; Foo f : v)
//   ^^^^^^^^^^^^^^^ init-statement
{
    (void)f;
}

for (typedef struct { int x; int y;} P; auto [x, y] : {P{1, 1}, {1, 2}, {3, 5}})
//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ init-statement
{
    (void)x;
    (void)y;
}

während ein Alias-Deklaration ist nicht ein init-Anweisungund somit nicht dürfen in Kontexten verwendet werden, die Initialisierungsanweisungen zulassen

// C++ 11.
for (using Foo = int; Foo{} != 0;) {}
//   ^^^^^^^^^^^^^^^ error: expected expression

// C++17 (initialization expressions in switch and if statements).
if (using Foo = int; true) { (void)Foo{}; }
//  ^^^^^^^^^^^^^^^ error: expected expression

switch (using Foo = int; 0) { case 0: (void)Foo{}; }
//      ^^^^^^^^^^^^^^^ error: expected expression

// C++20 (range-based for loop initialization statements).
std::vector<int> v{1, 2, 3};
for (using Foo = int; Foo f : v) { (void)f; }
//   ^^^^^^^^^^^^^^^ error: expected expression

Sie sind im Wesentlichen gleich, aber using bietet alias templates was ganz nützlich ist. Ein gutes Beispiel, das ich finden konnte, ist wie folgt:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

Also können wir verwenden std::add_const_t<T> anstatt typename std::add_const<T>::type

  • Soweit ich weiß, ist es ein undefiniertes Verhalten, etwas innerhalb des std-Namespace hinzuzufügen

    – jemand mit PC

    10. März 2019 um 16:15 Uhr

  • @someonewithpc Ich habe nichts hinzugefügt, es existiert bereits, ich habe nur ein Beispiel für die Verwendung von Typnamen gezeigt. Bitte prüfe de.cppreference.com/w/cpp/types/add_cv

    – Validus Oculus

    11. März 2019 um 2:18 Uhr

1647149416 613 Was ist der Unterschied zwischen „typedef und „using in C11
Roboterwald

Ich weiß, dass das Originalposter eine großartige Antwort hat, aber für alle, die wie ich über diesen Thread stolpern, gibt es einen wichtigen Hinweis von der Antrag das meiner Meinung nach etwas Wertvolles zur Diskussion hier hinzufügt, insbesondere zu den Bedenken in den Kommentaren darüber, ob die typedef Schlüsselwort wird in Zukunft als veraltet markiert oder entfernt, weil es redundant/alt ist:

Es wurde vorgeschlagen, das Schlüsselwort typedef … (wieder) zu verwenden, um Template-Aliase einzuführen:

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

Diese Notation hat den Vorteil, dass ein bereits bekanntes Schlüsselwort verwendet wird, um einen Typenalias einzuführen. Allerdings weist es auch einige Nachteile auf [sic] darunter die Verwirrung bei der Verwendung eines Schlüsselworts, von dem bekannt ist, dass es einen Alias ​​für einen Typnamen in einem Kontext einführt, in dem der Alias ​​keinen Typ, sondern eine Vorlage bezeichnet; Vec ist nicht ein Alias ​​für einen Typ und sollte nicht für einen Typedef-Namen genommen werden. Der Name Vec ist ein Name für die Familie std::vector<•, MyAllocator<•> > – wobei das Aufzählungszeichen ein Platzhalter für einen Typnamen ist. Folglich schlagen wir nicht die „typedef“-Syntax vor. Andererseits wird der Satz

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

kann gelesen/interpretiert werden als: ab jetzt verwende ich Vec<T> als Synonym für std::vector<T, MyAllocator<T> >. Mit dieser Lektüre erscheint die neue Syntax für Aliasing einigermaßen logisch.

Für mich impliziert dies eine fortgesetzte Unterstützung für die typedef Schlüsselwort in C++, weil es noch mehr Code machen kann lesbar und verständlich.

Aktualisieren der using Schlüsselwort war speziell für Vorlagen und (wie in der akzeptierten Antwort darauf hingewiesen wurde) wenn Sie mit Nicht-Vorlagen arbeiten using und typedef sind mechanisch identisch, so dass die Wahl aus Gründen der Lesbarkeit und der Mitteilung der Absicht vollständig dem Programmierer überlassen bleibt.

  • Soweit ich weiß, ist es ein undefiniertes Verhalten, etwas innerhalb des std-Namespace hinzuzufügen

    – jemand mit PC

    10. März 2019 um 16:15 Uhr

  • @someonewithpc Ich habe nichts hinzugefügt, es existiert bereits, ich habe nur ein Beispiel für die Verwendung von Typnamen gezeigt. Bitte prüfe de.cppreference.com/w/cpp/types/add_cv

    – Validus Oculus

    11. März 2019 um 2:18 Uhr

1647149416 677 Was ist der Unterschied zwischen „typedef und „using in C11
marski

Beide Schlüsselwörter sind gleichwertig, es gibt jedoch einige Einschränkungen. Eine davon ist die Deklaration eines Funktionszeigers mit using T = int (*)(int, int); ist klarer als mit typedef int (*T)(int, int);. Zweitens ist das Template-Alias-Formular nicht möglich typedef. Drittens würde das Offenlegen der C-API erforderlich sein typedef in öffentlichen Kopfzeilen.

996130cookie-checkWas ist der Unterschied zwischen „typedef“ und „using“ in C++11?

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

Privacy policy