新代码一律用using而非typedef,因其支持模板别名、语法更清晰、类内继承更一致,且是泛型基础设施;typedef不支持模板、易误读、维护性差。

新代码一律用 using,旧项目里遇到 typedef 不必强改,但新增别名必须用 using——这不是风格偏好,而是能力边界问题。
模板别名只能用 using,typedef 语法上不支持
只要涉及模板参数,typedef 就直接失效。比如想让 Vec<int></int> 等价于 std::vector<int></int>:
-
template<typename t> using Vec = std::vector<t>;</t></typename>✅ 合法,可实例化、可推导、可参与 SFINAE -
template<typename t> typedef std::vector<t> Vec;</t></typename>❌ 编译报错:'T' was not declared in this scope
有人试图绕过:用 struct 包一层再 typedef 内部类型,结果是写法臃肿、无法做别名模板特化、不能用于类型萃取上下文。
函数指针和数组类型用 using 更少出错
typedef 对括号和方括号位置极其敏感,稍一错位语义就完全改变:
-
using FuncPtr = int(*)(double, const std::string&);—— 一眼看出是“函数指针” -
typedef int (*FuncPtr)(double, const std::string&);—— 初学者常误读成“返回int*的函数” -
typedef int *FuncPtr(int);—— 这其实是声明一个函数,不是指针别名,编译器不报错但逻辑全错
数组同理:using IntArray5 = int[5]; 比 typedef int IntArray5[5]; 更直观,尤其多维时:using Matrix = double[10][10]; 直接可读。
类内继承和偏特化场景下 using 行为更一致
在模板类中重导 value_type 或 iterator 时:
-
using value_type = typename Base::value_type;—— 可直接继承父类模板参数,无需额外typename声明 -
typedef typename Base::value_type value_type;—— 在某些嵌套深度下需反复加typename,容易漏
using 定义的别名模板可被偏特化(如 template using Vec<bool> = std::deque<bool>;</bool></bool>),而 typedef 定义的类型别名没有模板语义,无法参与这类泛型机制。
真正容易被忽略的是:模板别名不是“语法糖”,它是泛型基础设施——自定义分配器容器、策略包装、类型擦除适配器,没 using 就得靠宏或冗余结构体硬凑,可维护性会断崖下跌。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











