为什么 c++开发总喜欢定义别名呢(typedef/#define)

2021-08-29 17:20:27 +08:00
 killergun

不会仅为了写代码的时候 减少字符数?

2330 次点击
所在节点    问与答
13 条回复
BiteTheDust
2021-08-29 17:48:25 +08:00
还有 using
ipwx
2021-08-29 17:56:04 +08:00
1. 减少字符。
2. 方便切换类型。

有关切换类型:比如 typedef std::shared_ptr<XX>

如果你后期想优化性能,把这个 shared_ptr 变成 memory_pool based smart_ptr (自己实现的),那你就明白这东西的好处了。

3. 配合模板

比如 template <typename Container>
class XXX{
typedef typename Container::value_type value_type;
};
ipwx
2021-08-29 17:56:48 +08:00
ps. 配合模板指的是,上面这个例子,我可以通过 XXX<std::vector<int>>::value_type 得到 int 了。
fgwmlhdkkkw
2021-08-29 17:57:58 +08:00
你是写 Java 的吧🧐
Hconk
2021-08-29 18:04:22 +08:00
typedef 和 define 完全是两个东西,typedef 和 using 一样是在编译阶段生效,define 是在编译前的预处理阶段进行替换。

先说 typedef 和 using,C++如果导出函数给别的语言最简单的方式就是提供 C 风格的接口,如果不用 typedef 起个别名看到一堆 void* ,uint32 很迷惑,这一点在 Windows API 里面多,这种情况下用不了 using 。

还有你提到的为了减少变量类型长度,如果你用过 ITK 这种模版范式写过的库就知道,要是不起个别名的话每次定义个变量都很麻烦,这种情况下更推荐用 using 。定义模板的别名只能用 using 。

#define 有些情况下没法替换,或者不用宏写起来很麻烦,具体可以看看这个 https://www.zhihu.com/question/30659549/answer/49956788
ipwx
2021-08-29 18:12:02 +08:00
@Hconk 它后面两个例子我没有异议。不过第一个例子( LOOP_UNROLL_DOUBLE ):

可以用

template <typename Fn1, typename Fn2>
inline void loopUnrolDouble(const Fn1& fn1, const Fn2& fn2) {
...
}

loopUnrollDouble(
[&] () {
...
},
[&] () {
...
}
);

开 -O3 应该会直接内联调用。当然我没真的反汇编看过,不过应当如此。所以 lambda 是好东西。
ipwx
2021-08-29 18:12:35 +08:00
另外 const Fn1& const Fn2& 更现代一点可能会用 Fn1&& Fn2&& ,不过我觉得 -O3 就没去别了。
QBugHunter
2021-08-29 19:25:28 +08:00
1.减少字符
2.方便阅读代码
zxCoder
2021-08-29 19:48:02 +08:00
风格,千万不要拿别的语言那一套去看 c++
TypeError
2021-08-29 21:33:40 +08:00
go 也推荐定义别名,增加可读性+方便替换扩展吧
Caturra
2021-08-29 22:01:12 +08:00
我觉得,某种角度来看,STL 本身就是靠一堆别名堆砌而成的,

以容器为例,一个容器如 vector<T, alloc> / list<T, alloc>内部有声明::value_type 、::reference 、::iterator 、blabla 等别名,这些主要是方便类型萃取,

比如你写个通用的排序函数,接口就简单点 sort(Container&),表示对整个容器进行排序
那么问题来了,怎么知道各种容器内的类型 T,最简单的萃取是通过 using T = typename Container::value_type 就能知道
(当然你不用任何别名也可以,这个时候就需要自己写一个重载、Traits 类特化偏特化、SFINAE 等操作去支持,自找苦吃)

各种迭代器 iterator 就更不用说了,实现 iterator 也是和容器一样规定了各种别名,并且有专门的萃取类型来辅助处理里面的别名,从而实现在模板的世界里为所欲为
https://en.cppreference.com/w/cpp/iterator/iterator_traits

也有一些设计 policy based 过于魔怔了,不得不用别名降低点阅读难度的例子,比如 gcc/hashtable.h,
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/hashtable.h
(当前的版本)从 207 行开始就用了一堆的 using,你要是不用,那还真是整段代码没法看了

如果你说 C++里面别名总是用#define,那我见识短,还没遇到过非用不可的情况
mingl0280
2021-08-30 04:41:41 +08:00
因为定义别名真的方便阅读……
你看到一个 xxxx_TIMEOUT 的 define 就知道这个值是个超时了。
不要随便把 magic number 放得程序里到处都是,这样能节约大量的阅读时间。
还有一个用途是省空间。我之前写的一个回调的 using 大概长这样:
```
using funcProto = int(unsigned char*, unsigned int, unsigned int, int&, int&);
```
然后放在 std::function 里面就可以写成
```
std::function<funcProto> some_func = reinterpret_cast<funcProto*>(GetProcAddress(lib_handle, "FunctionName"));
```
这样。
如果你直接用原始的话这一行会变成多长……
iceheart
2021-08-30 08:06:35 +08:00
typedef 一般是模板类用的多,遵循依赖倒置原则,解耦外部依赖

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/798674

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX