类型定义的使用差异using/typedef/define/constexpr

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

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

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

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

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

列表对比

关键字 本质 用途 作用域 类型安全 推荐度
using C++11 现代别名 类型别名(首选) 编译期、作用域安全 ✅ 强类型安全 ⭐⭐⭐⭐⭐
typedef C 老式别名 类型别名(兼容旧代码) 编译期、作用域安全 ✅ 强类型安全 ⭐⭐⭐
#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(仅兼容旧代码)
c 复制代码
#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
// ==========================
constexpr int MAX_COUNT = 100;
constexpr double PI = 3.14159;
constexpr bool IS_DEBUG = true;

// 用于数组大小 / 模板参数
constexpr int ARR_SIZE = 5;
int arr[ARR_SIZE];                  // 数组大小
std::array<int, ARR_SIZE> arr_std;  // 模板参数

// ==========================
// 3. ❌ 禁止:#define 定义类型
// ==========================
// #define MyInt int*  // 纯文本替换,极易出 Bug

// ==========================
// 4. typedef(仅兼容旧代码)
// ==========================
typedef int OldInt;
typedef void(*OldFuncPtr)(int);

3、语法详解

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

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

  • 语法:新名字 = 旧类型,直观易懂
  • 支持函数指针、模板别名(typedef 做不到)
  • 作用域安全:在类/函数内定义只在内部生效
  • 编译期处理,无运行时开销
用法
cpp 复制代码
// 给类型起别名
using MyInt = int;
using StrVector = std::vector<std::string>;

// 函数指针别名(比 typedef 好读 10 倍)
using FuncPtr = int(*)(int, int);

// 模板别名(typedef 做不到!)
template <typename T>
using Vec = std::vector<T>;

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

不是类型别名 ,是定义编译期常量 ,常用来替代define方式的常量定义,例如定义PI值,均应优先使用constexpr方式。

用途:数组大小、模板参数、全局常量配置

特点:

  • 类型安全,作用域安全
  • 编译期求值,无运行时开销
  • 用于常量值,不是给类型起别名
用法
cpp 复制代码
constexpr int MAX = 1024;
constexpr int square(int x) { return x*x; }
constexpr int res = square(10); // 编译期直接算出 100

3.3. typedef(老式类型别名)

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

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

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

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

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

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

4.1. using vs typedef(都是类型别名)

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

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

4.2. 宏 #define 真的危险吗?

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

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

cpp 复制代码
#define MyInt int*
MyInt a, b;  // a 是指针,b 是 int!

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

4.3. constexpr 到底干嘛的?

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

用于:

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

示例:

cpp 复制代码
// 1. 数组大小
constexpr int N = 10;
int arr[N];  // 合法,N 是编译期常量
// 2. 模板参数
constexpr int ARRAY_SIZE = 5;
std::array<int, ARRAY_SIZE> my_array; 
// 3. 常量配置
constexpr double PI = 3.1415926;

// 不建议的方式
#define N 10
int arr[N];  // 也能用,但不安全、无类型

5、总结实践

5.1 推荐用法

cpp 复制代码
#include <vector>
#include <map>
#include <array>
#include <string>

// 类型别名
using UserId = int;
using UserMap = std::map<std::string, UserId>;
using LogicFunc = bool(*)(int);

// 模板别名
template <typename T>
using MyArray = std::vector<T>;

// 编译期常量
constexpr int MAX_USER = 1024;
constexpr double CIRCLE_RATE = 3.1415926;
constexpr int BUF_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 )

相关推荐
智者知已应修善业1 小时前
【51单片机流水灯中断嵌套,低优先级中断完成后如何返回主程序】2023-10-15
c++·经验分享·笔记·算法·51单片机
lihongli0001 小时前
关于c++中锁的种类与使用
java·开发语言·c++
凤凰院凶涛QAQ1 小时前
《C++转Java快速入手系列》继承与多态篇
java·c++
whxnchy2 小时前
UDP多端口负载均衡实战
c++
叼烟扛炮3 小时前
C++ 知识点08 类与对象
开发语言·c++·算法·类和对象
楼田莉子3 小时前
仿Muduo的高并发服务器:Http协议模块
linux·服务器·c++·后端·学习
tjl521314_2110 小时前
04C++ 名称空间(Namespace)
开发语言·c++
ximu_polaris10 小时前
设计模式(C++)-行为型模式-备忘录模式
c++·设计模式·备忘录模式
tankeven14 小时前
C++ 智能指针
c++