C++中typedef的一些思考
引言
对于typedef,初学者最常用的是在C中对struct T类型名作简化,或者将long long定义成ll,但是typedef的内容远不如此。
在此篇文章中,我将记录下自己对typedef的理解,以供思考,如有不足之处欢迎指正。
正文
typedef与define
typedef是c++中的一个关键字,作用是为类型创建一个别名以供使用,如
struct Node{
int x;
struct Node* next;
};
typedef struct Node Node_t;
Node_t root;//等价于struct Node root;
这么看来typedef和define宏是很像的,只不过前后顺序不一样:
#define ll long long//define的类型名在前方
typedef long long ll;
对于一般的情况,使用typedef或者define,效果是完全相同的。 尽管如此,我还是建议使用typedef,因为define宏经常会造成一些不安全的结果,使得结果预期和实际情况不符,具体情况这里不作展开。
typedef作为c++关键字,在编译期被处理,因而语义被编译器所理解,安全性有所保证,也方便了调试和编写代码。
声明与定义
想要创建一个变量,我们有两种方式,声明和定义。 声明和定义外形上很相似,某些情况下甚至一起出现,我们区分二者的方式,是看变量是否被分配内存。 声明只是告诉编译器这里有一个T类型的变量X,而定义同时还为X分配了T类型的内存空间。
//变量
extern int x;//声明,未分配内存
int y;
int z=10;//两个均是定义,均分配了内存,且z被初始化
//函数
int add(int x,int y);//声明函数
int add(int x,int y){
return x+y;
}//定义函数内容
//结构体
struct Node;//声明结构体
struct Node{
int x;
struct Node* next;
}//定义结构体内容
struct Node root;//定义变量且分配内存
对于同一变量,可以多次声明,但是只能定义一次,这也可以作为一个判别方式
实际上,所有的定义都是声明,但声明不一定是定义。我们一般说的声明是纯声明,定义是包含定义的声明。
typedef语法
对于typedef的深入认识,需要从其语法开始理解。
typedef的公认语法是用在声明语法之前,表示将声明中的变量名提升至类型名
考虑到有"typedef int t"这种使用,我认为这里的声明还包括无初始化的定义
除了基础类型和指针,typedef的其他用法均是#define无法做到的
typedef int int_t;
int_t x;//int x;
typedef int* pint_t;
pint_t y;//int* y;
typedef int array_t[10];
array_t z;//int z[10];
typedef struct Node{
int x;
struct Node* next;
}Node_t;
Node_t w;//struct Node w;
typedef int (*pfun_t)(int ,int );
pfun_t add;//int (*add)(int ,int );
很明显可以看出typedef定义的类型名在定义变量时,可以直接用变量名替代类型名的位置来获取变量的类型。
对于函数指针的一些理解
写这篇文章的动机来源于小彭老师讲授的std::function实现过程,中间出现了
typedef void (*pfun);
//或者带参
typedef void (*pfun)(int,char*);
这让我联想到一般的定义语句如int x,使用x相当于取x内存地址中的值返回解析成int数据。如果我们把函数名当作一个变量来理解,会好理解的多:
(*pfun)表示一个函数变量,是对pfun的解引用,则pfun是一个指向返回值为空的无参函数的函数指针。
而实际上,函数在汇编代码中,也确实是一段内存地址,和变量的区别只是存放的段不一样,所以这样理解应该是没有什么问题的。
补充要点
typedef用于将类型封装成别名,别名使用时必须当作一个整体来看待。
typedef char* str;
const str s;//const修饰str类型整体,所以s是一个const指针,但是指向的字符数组内容可以变化。
//想要指向const内容必须在typedef时定义
typedef const char* str;
另外,typedef不能直接模板化,模板化建议使用using。
小结
typedef本身确实不难,但是其背后的思想值得学习借鉴。
$ 正在加载评论…