类型定义的使用差异using/typedef/define/constexpr
2026/5/9 6:55:29 网站建设 项目流程

( Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu )

1、C++ 类型定义:using / typedef / #define / constexpr 对比

usingtypedef#defineconstexpr是 C++ 给类型或值起别名的核心关键字。

  • using/constexpr:C++11 现代写法,强烈推荐
  • typedef:老式写法,仅兼容旧代码
  • #define:纯文本替换,严禁用于类型/常量

下面从用途、原理、作用域、安全性方面,列表对比来看。

列表对比

关键字本质用途作用域类型安全推荐度
usingC++11 现代别名类型别名(首选)编译期、作用域安全✅ 强类型安全⭐⭐⭐⭐⭐
typedefC 老式别名类型别名(兼容旧代码)编译期、作用域安全✅ 强类型安全⭐⭐⭐
#define纯文本宏替换文本替换(极不推荐用于类型)全局、无作用域❌ 无类型、易出BUG
constexpr编译期常量表达式常量值定义编译期、作用域安全✅ 强类型安全⭐⭐⭐⭐⭐

归纳总结:

  1. 定义类型别名 → 优先用using;(函数指针也用它)
  2. 定义编译期常量 → 用constexpr,替代define方式的常量定义;
  3. 绝对不要用#define定义类型/常量;
  4. typedef` 仅用于兼容旧代码。

定义类型别名

定义编译期常量

禁止操作

兼容场景

开始:需要定义类型/常量

需求类型

优先使用 using

使用 constexpr

绝对不要用 #define 定义类型

typedef 仅用于兼容旧代码

结束

2、代码样例

    1. 类型别名 → 用 using(推荐)
    1. 编译期常量 → 用 constexpr
    1. ❌ 禁止:#define 定义类型
    1. typedef(仅兼容旧代码)
#include<array>#include<vector>#include<map>#include<string>// ==========================// 1. 类型别名 → 用 using(推荐)// ==========================using MyInt=int;using StrMap=std::map<std::string,std::string>;// 函数指针(最清晰写法)using FuncPtr=void(*)(int,double);// 模板别名(using 独有功能)template<typename T>using MyVec=std::vector<T>;// ==========================// 2. 编译期常量 → 用 constexpr// ==========================constexprintMAX_COUNT=100;constexprdoublePI=3.14159;constexpr bool IS_DEBUG=true;// 用于数组大小 / 模板参数constexprintARR_SIZE=5;intarr[ARR_SIZE];// 数组大小std::array<int,ARR_SIZE>arr_std;// 模板参数// ==========================// 3. ❌ 禁止:#define 定义类型// ==========================// #define MyInt int* // 纯文本替换,极易出 Bug// ==========================// 4. typedef(仅兼容旧代码)// ==========================typedefintOldInt;typedefvoid(*OldFuncPtr)(int);

3、语法详解

3.1.using(C++11 现代类型别名)

最推荐、最强大、语法最直观,完全替代typedef

  • 语法:新名字 = 旧类型,直观易懂
  • 支持函数指针、模板别名(typedef 做不到)
  • 作用域安全:在类/函数内定义只在内部生效
  • 编译期处理,无运行时开销
用法
// 给类型起别名usingMyInt=int;usingStrVector=std::vector<std::string>;// 函数指针别名(比 typedef 好读 10 倍)usingFuncPtr=int(*)(int,int);// 模板别名(typedef 做不到!)template<typenameT>usingVec=std::vector<T>;

3.2.constexpr(编译期常量表达式)

不是类型别名,是定义编译期常量,常用来替代define方式的常量定义,例如定义PI值,均应优先使用constexpr方式。
用途:数组大小、模板参数、全局常量配置
特点:

  • 类型安全,作用域安全
  • 编译期求值,无运行时开销
  • 用于常量值,不是给类型起别名
用法
constexprintMAX=1024;constexprintsquare(intx){returnx*x;}constexprintres=square(10);// 编译期直接算出 100

3.3. typedef(老式类型别名)

C 语言遗留,C++ 为了兼容保留,语法不易懂,不推荐新代码使用

  • 语法顺序混乱:typedef 旧类型 新名字
  • 不支持模板别名
  • 复杂类型可读性极差(如函数指针、嵌套类型)
// 等价于 using MyInt = int;typedefintMyInt;// 函数指针(可读性差),等价于using FuncPtr = int(*)(int, int);typedefint(*FuncPtr)(int,int);

3.4. define定义(纯文本宏,危险!)

预处理阶段文本替换不是类型定义绝对不要用来定义类型

  • 预处理阶段替换,不是 C++ 语法
  • 无作用域、无类型检查、极易产生隐蔽 Bug
#defineMyIntint*MyInt a,b;// 展开后:int* a, b;// a 是指针,b 是普通 int!完全错误

4、关键的区别~面试常问

4.1.usingvstypedef(都是类型别名)

  • using语法更清晰,支持模板,是现代 C++ 标准
  • typedef语法不易懂,无模板支持,仅用于兼容旧代码

规则:新项目一律用using,不用typedef

4.2. 宏#define真的危险吗?

因为define是纯文本替换,不是类型定义,会产生难以发现的 Bug。

非常危险!看这个经典BUG:

#defineMyIntint*MyInt a,b;// a 是指针,b 是 int!usingMyInt=int*;MyInt a,b;// a、b 都是指针,正确!

4.3.constexpr到底干嘛的?

不定义类型别名,只定义编译期就能确定的值
用于:

  • 数组大小
  • 模板参数
  • 常量配置

示例:

// 1. 数组大小constexprintN=10;intarr[N];// 合法,N 是编译期常量// 2. 模板参数constexprintARRAY_SIZE=5;std::array<int,ARRAY_SIZE>my_array;// 3. 常量配置constexprdoublePI=3.1415926;// 不建议的方式#defineN10intarr[N];// 也能用,但不安全、无类型

5、总结实践

5.1 推荐用法

#include<vector>#include<map>#include<array>#include<string>// 类型别名usingUserId=int;usingUserMap=std::map<std::string,UserId>;usingLogicFunc=bool(*)(int);// 模板别名template<typenameT>usingMyArray=std::vector<T>;// 编译期常量constexprintMAX_USER=1024;constexprdoubleCIRCLE_RATE=3.1415926;constexprintBUF_SIZE=64;// 编译期常量用于容器模板参数std::array<int,BUF_SIZE>buf;

5.2 总结

  1. 给类型起别名:优先using,完全替代typedef
  2. 定义编译期常量:用constexpr
  3. typedef:仅维护旧代码时使用,新项目不用
  4. 文本宏define:绝不用于类型/常量,只在极端底层场景使用

( Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu )

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询