typedef vs using in C++: Vollständige Anleitung für moderne Entwickler
\n\nHaben Sie sich jemals gefragt, warum im C++-Code einige Entwickler typedef schreiben und andere using? Es scheint, dass beide dasselbe tun – sie erstellen Aliase für Typen. Aber ist das wirklich so? Wenn Sie sauberen, modernen Code schreiben und nicht in die Fallstricke veralteter Konstruktionen tappen möchten, ist dieser Artikel genau das Richtige für Sie.
Wir werden herausfinden, worin sich typedef und using in C++ unterscheiden, wann man was verwendet und warum die C++-Community immer mehr zu using tendiert. Bereit? Los geht's!
Kurze Geschichte: Von C bis C++11
\n\ntypedef stammt aus der Sprache C. Es ist die klassische Methode, einen Alias für einen Typ zu deklarieren. Es sieht so aus:
\n\ntypedef unsigned long long ULL;\ntypedef std::vector<std::string> StringVector;\ntypedef void (*FunctionPtr)(int, double);\n\nDie Syntax ist, gelinde gesagt, nicht die intuitivste. Besonders auffällig wird dies bei Zeigern auf Funktionen – selbst erfahrene Entwickler stolpern manchmal beim Lesen solcher Deklarationen.
\n\nIn C++11 wurde eine neue Konstruktion eingeführt – using (auch Alias-Deklaration genannt). Sie sieht viel natürlicher aus:
\n\nusing ULL = unsigned long long;\nusing StringVector = std::vector<std::string>;\nusing FunctionPtr = void (*)(int, double);\n\nMan sieht sofort: links der Name, rechts der Typ. Es liest sich wie eine „Zuweisung", was für jeden Programmierer intuitiv verständlich ist.
\n\nDer Hauptunterschied: Arbeit mit Templates
\n\nHier liegt der wichtigste Unterschied zwischen typedef und using. using unterstützt Alias Templates (Template-Aliase), typedef hingegen nicht.
Schauen wir uns das an einem Beispiel an. Angenommen, Sie möchten einen Alias für std::unique_ptr mit einem benutzerdefinierten Deleter erstellen:
// Mit using – einfach und elegant\ntemplate <typename T>\nusing CustomPtr = std::unique_ptr<T, void(*)(T*)>;\n\n// Mit typedef – direkt nicht möglich!\n// Man muss Umwege über Strukturen gehen\ntemplate <typename T>\nstruct CustomPtrOld {\n typedef std::unique_ptr<T, void(*)(T*)> type;\n};\n\n// Verwendung:\nCustomPtr<int> ptr1; // using – einfach\nCustomPtrOld<int>::type ptr2; // typedef – umständlich\n\nSpüren Sie den Unterschied? using macht den Code sauberer und kürzer. Und wenn Sie einen solchen Alias innerhalb einer Template-Klasse oder -Funktion verwenden müssen, wird der Unterschied noch deutlicher:
template <typename T>\nclass Container {\npublic:\n // Mit using\n using Ptr = CustomPtr<T>;\n \n // Mit typedef – benötigt typename und ::type\n typedef typename CustomPtrOld<T>::type OldPtr;\n \nprivate:\n Ptr data;\n OldPtr oldData;\n};\n\nLesbarkeit des Codes: Ein klarer Gewinner
\n\nSelbst bei einfachen Typen punktet using in der Lesbarkeit. Vergleichen Sie:
// Mit typedef – unklar, wo Name und wo Typ ist\ntypedef std::map<std::string, std::vector<int>> StringToIntVectorMap;\n\n// Mit using – alles offensichtlich\nusing StringToIntVectorMap = std::map<std::string, std::vector<int>>;\n\nWenn Sie Code lesen, scannt Ihr Auge die Konstruktion natürlicherweise von links nach rechts. using folgt diesem Prinzip: zuerst der Name, dann der Typ. typedef hingegen zwingt Sie, zuerst den Typ und dann den Namen zu lesen – das widerspricht der Intuition.
Zeiger auf Funktionen: Der Schmerz von typedef
\n\nZeiger auf Funktionen sind wohl der am wenigsten geliebte Teil von C++ für viele Entwickler. Und typedef macht sie noch verwirrender:
// typedef – lesen Sie es wie einen Zauberspruch\ntypedef void (*Callback)(int, const std::string&);\n\n// using – wie eine normale Variable\nusing Callback = void (*)(int, const std