找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 1179|回复: 2

【翻译】【C++】现代C艹中的using与typedef

[复制链接]

1110

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24217 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
发表于 2022-2-15 12:00:37 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×

现代C++中的usingtypedef

原文:https://www.internalpointers.com/post/differences-between-using-and-typedef-modern-c
译者:0xAA55

清爽的类型别名定义方式

为何使用类型别名

从初学C语言的时候,我们就已经掌握了通过给变量类型起别名的方式来避免代码变得过于复杂或者意义不明。简而言之,你可以给一个现有的变量类型(比如int)取一个新的名字(比如Pixel)。类型别名可用于帮助你书写清爽、干净且易于阅读的代码。

假设你正在弄一个图形库,请观察以下两个函数的差异。

int getScreenWidth();

或者:

Pixel getScreenWidth();

后者显然更直观,在声明了别名Pixel后,它返回的数值是干什么的就一目了然了。
另一个例子如下:

std::map<std::string, std::vector<std::string>> map;

或者:

Map map;

需要注意使用类型别名并不意味着创建新的类型。它只是以同义词的方式来指代原有的类型名。上文的Pixel依然是个int,且Map依然是鬼畜的std::map<std::string, std::vector<std::string>>,可以被用在只接受int或者std::map<std::string, std::vector<std::string>>类型的参数的函数调用上(而并不需要函数的参数非得是Pixel或者Map)。

声明新别名的方式

在现代C++里有两种方式声明类型别名,第一种是传统的typedef关键字:

typedef [原有类型] [你要的别名];

例如:

typedef int Pixel;
typedef std::map<std::string, std::vector<std::string>> Map;

而另一种声明别名的方式则是通过使用从C++11开始引入的using关键字来实现的:

using [你要的别名] = [原有类型];

例如:

using Pixel = int;
using Map = std::map<std::string, std::vector<std::string>>;

效果上,这两种方式是相同的。最终你都可以使用PixelMap这两个你定义的新名称,想怎么用就怎么用。但……

using最适合模板

上文的Map的定义(不管是用typedef还是using)它本来的类型已经被定死了:永远只会是一个std::map<std::string, std::vector<std::string>>,改不了的,比如你想用一个类型为std::map<int, std::vector<int>>Map,你就得重新用另一个别名了。

但C++11的using其实能够创建“模板别名”:可以给类型模板起别名。它打开了一扇门,使你能指定原有类型里的模板参数。
定义的方式如下:

template<[模板参数列表]> using [你要的别名] = [原有类型];

例如:

template<typename T1, typename T2> using Map = std::map<T1, std::vector<T2>>;

然后我就可以定义不同类型的Map变量了:

// 实际类型:std::map<std::string, std::vector<std::string>> (和上文例子里相同)
Map<std::string, std::string> map1;

// 实际类型:std::map<int, std::vector<int>>
Map<int, int> map2;

// 实际类型:std::map<int, std::vector<float>>
Map<int, float> map3;

虽然其实使用传统的typedef也可以实现相同的效果,但是非常难设计、复杂棘手。不值得弄。

模板声明不能被放在代码块里

你可以把类型别名定义放在任何位置,不管是用typedef还是using,你都可以放在任意地方:命名空间里、类里,或者块里({}里面)

但模板别名则和别的C++模板一样遵循一个规则:它们不能被放在块里,因为它们最终都是模板定义,所以都是放在命名空间里,或者不使用命名空间的时候放全局位置。

参考来源

cprogramming.com - The Typedef Keyword in C and C++
cppreference.com - Type alias, alias template
cppreference.com - typedef specifier
StackOverflow - What is the difference between 'typedef' and 'using' in C++11?

回复

使用道具 举报

55

主题

275

回帖

9352

积分

用户组: 管理员

UID
77
精华
16
威望
237 点
宅币
8217 个
贡献
251 次
宅之契约
0 份
在线时间
254 小时
注册时间
2014-2-22
发表于 2022-2-15 15:26:35 | 显示全部楼层
就是语法糖。

但我认为这不是啥好事情,每个人都选择性用不同的语法做同样的事情,这导致代码的可交流性降低,因为大部分程序员不可能了解所有的语法。

所以吧,我写代码的时候,还是坚持用C99标准。一些老人写C代码的时候,甚至还坚持用C89标准。
回复 赞! 靠!

使用道具 举报

1110

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24217 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
 楼主| 发表于 2022-2-18 16:53:22 | 显示全部楼层
美俪女神 发表于 2022-2-15 15:26
就是语法糖。

但我认为这不是啥好事情,每个人都选择性用不同的语法做同样的事情,这导致代码的可交流性降 ...

那你敢不敢写C语言的时候不使用一句宏?
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-17 07:00 , Processed in 0.048521 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表