为什么 c++开发总喜欢定义别名呢(typedef/#define) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
killergun
V2EX    问与答

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

  •  
  •   killergun 2021-08-29 17:20:27 +08:00 2711 次点击
    这是一个创建于 1555 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    13 条回复    2021-08-30 08:06:35 +08:00
    BiteTheDust
        1
    BiteTheDust  
       2021-08-29 17:48:25 +08:00
    还有 using
    ipwx
        2
    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
        3
    ipwx  
       2021-08-29 17:56:48 +08:00
    ps. 配合模板指的是,上面这个例子,我可以通过 XXX<std::vector<int>>::value_type 得到 int 了。
    fgwmlhdkkkw
        4
    fgwmlhdkkkw  
       2021-08-29 17:57:58 +08:00
    你是写 Java 的吧
    Hconk
        5
    Hconk  
       2021-08-29 18:04:22 +08:00 via iPhone
    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
        6
    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
        7
    ipwx  
       2021-08-29 18:12:35 +08:00
    另外 const Fn1& const Fn2& 更现代一点可能会用 Fn1&& Fn2&& ,不过我觉得 -O3 就没去别了。
    QBugHunter
        8
    QBugHunter  
       2021-08-29 19:25:28 +08:00
    1.减少字符
    2.方便阅读代码
    zxCoder
        9
    zxCoder  
       2021-08-29 19:48:02 +08:00
    风格,千万不要拿别的语言那一套去看 c++
    TypeError
        10
    TypeError  
       2021-08-29 21:33:40 +08:00 via Android
    go 也推荐定义别名,增加可读性+方便替换扩展吧
    Caturra
        11
    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
        12
    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
        13
    iceheart  
       2021-08-30 08:06:35 +08:00 via Android
    typedef 一般是模板类用的多,遵循依赖倒置原则,解耦外部依赖
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3145 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 11:43 PVG 19:43 LAX 03:43 JFK 06:43
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86