C++ 提供兩種建立別名的機制:
typedef / using — 作用於 **型別層級**,編譯期概念混淆兩者會導致設計錯誤。本文深度剖析兩者本質差異、適用場景與現代最佳實務。
typedef int Int32;
typedef char* PChar;
typedef void (*Callback)(int);
typedef std::map<std::string, int> StringIntMap;
// 缺點:函式指標、模板語法難讀,不支援模板別名
using Int32 = int;
using PChar = char*;
using Callback = void(*)(int);
using StringIntMap = std::map<std::string, int>;
// 模板別名 (typedef 做不到)
template <typename T>
using Vec = std::vector<T>;
Vec<int> vi; // std::vector<int>
Vec<std::string> vs; // std::vector<std::string>
// 函式指標陣列別名
using FuncPtrArray = void(*)[10](int);
| 特性 | typedef | using |
|---|---|---|
| 語法統一性 | 型別在前/中/後不固定 | 一律 using NewName = Type; |
| 模板別名 | 不支援 | 支援 (C++11) |
| 模板特化 | 需用 struct 包裝 | 直接特化 using |
| 作用域 | 遵循一般作用域規則 | 相同 |
| 編譯期實體 | 是 (無執行期開銷) | 是 |
int a = 5;
int& b = a; // b 是 a 的別名,非新物件
// 編譯器內部:b 共享 a 的記憶體位址
// &a == &b // 永遠為 true
// sizeof(b) == sizeof(int) // 非指標大小
| 特性 | 參考 (T&) | 指標 (T*) |
|---|---|---|
| 初始化 | **宣告時必須綁定**,不可延遲 | 可先宣告,稍後賦值 |
| 重新綁定 | **不可** (一旦綁定終身不變) | 可隨時指向其他物件 |
| 空值 | **不存在空參考** (除非 UB) | 可為 nullptr |
| 記憶體佈局 | 通常不佔額外儲存 (編譯器優化) | 佔指標大小儲存空間 |
| 語法存取 | 透明 (b = 3 直接操作 a) | 需解參考 (*p = 3) |
| 參數傳遞 | 呼叫端語法同傳值,被呼叫端為別名 | 需取址 &x |
obj.SetX(1).SetY(2)for (auto& x : vec) 避免拷貝、可修改元素auto& ref = veryLongVariableName; 簡化代碼C# 無 typedef,但有 using 別名導向:
// C#
using People = MyProject.Human; // 型別別名 (僅限檔案/命名空間作用域)
namespace MyProject {
class Human { public int Age; public void Talk() {} }
class Program {
static void Main() {
People p = new Human(); // 使用別名
p.Age = 50;
p.Talk();
}
}
}
差異:C# using 別名僅為編譯期語法糖,IL 中仍為完整型別名;C++ using/typedef 同樣純編譯期,但支援模板別名等進階功能。
// 標準庫型別特徵大量使用 using 別名
template <class T> struct remove_reference { using type = T; };
template <class T> struct remove_reference<T> { using type = T; };
template <class T> struct remove_reference<T&&> { using type = T; };
// C++14 別名模板簡化
template <class T> using remove_reference_t = typename remove_reference<T>::type;
// 使用
remove_reference_t<int> // int
remove_reference_t<int&&> // int
using:語法統一、支援模板別名、可讀性優於 typedef。using Handle = void*; (Windows) / using Handle = int; (POSIX)using JsonMap = std::map<std::string, JsonValue>;using type = ...auto& [x,y] = pair;std::reference_wrapper 或指標/智慧指標const T&,非 T&型別別名 是編譯期的「語法捷徑」,物件別名 (參考) 是執行期的「記憶體共享綁定」。前者零開銷、後者零開銷但有生命週期約束。現代 C++ 開發:using 取代 typedef,參考取代指標 (非擁有語意時),std::reference_wrapper 處理需重新綁定/可為空的別名需求。