C++98中,我们如果想用简写的方式表达一个类型,那么可以使用typedef关键字:

typedef std::unique_ptr<std::unordered_map<std::string, std::string>> UPtrMapSS;

C++11中,提供了别名声明的语法来取代typedef:

using UPtrMapSS = std::unique_ptr<std::unordered_map<std::string, std::string>>;

既然这两种语法都可以代表对一种类型的简写,那为什么一定要用using而不是typedef呢?

理由之一是,用using来声明函数指针时会更直观一些:

typedef void (function*) (int, int);
using function = void (*) (int, int);

直观与否,见仁见智,这其实不是一个非常必要的原因。using真正强大的地方在于它对模板的支持。

比方说我们要声明一个模板类型的简写,用using可以非常简单地实现:

template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>; MyAllocList<Widget> lw;

如果要用typedef的话,就会变得非常麻烦了:

template<typename T>
struct MyAllocList{
typedef std::list<T, MyAlloc<T>> type;
};
MyAllocList<Widget>::type lw;

除此之外,如果我们想在模板类中使用它,且MyAllocList的类型T是从模板形参指定的话,我们还要加上typename前缀:

template<typename T>
class Widget
{
private:
typename MyAllocList<T>::type l;
}

之所以要加typename是因为在这里编译器无法分辨MyAllocList::type究竟是MyAllocList里定义的类型还是一个成员变量,因此需要手动通过typename来标识一下。

如果使用的是using就完全不用关心这个问题,因为using本身就是在告诉编辑器这是一种类型。

template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>; template<typename T>
class Widget
{
private:
MyAllocList<T> l;
}

因此在日常写代码中,还是应当尽量都转换到以using来声明类型的别名,而不再使用typedef。

优先使用C++的别名声明(using)来替换typedef的更多相关文章

  1. Item 9: 比起typedef更偏爱别名声明(alias declaration)

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 我确信我们都同意使用STL容器是一个好主意,并且我希望在Item ...

  2. Linux中命令别名alias与命令替换

    当我们使用bash进行一些操作的时候,希望一些较为长的命令使用一些短的命令即可完成输入运行的话,我们就可以使用alias命令别名来帮助我们完成这个任务 alias作为一个bash的内置命令,具有一定的 ...

  3. Effective Modern C++:05右值引用、移动语义和完美转发

    移动语义使得编译器得以使用成本较低的移动操作,来代替成本较高的复制操作:完美转发使得人们可以撰写接收任意实参的函数模板,并将其转发到目标函数,目标函数会接收到与转发函数所接收到的完全相同的实参.右值引 ...

  4. Effective Modern C++:03转向现代C++

    07:在创建对象时注意区分()和{} 自C++11以来,指定初始化值的的方式包括使用小括号,等号,以及大括号: ); // initializer is in parentheses ; // ini ...

  5. 【c++ Prime 学习笔记】第2章 变量和基本类型

    2.1 基本内置类型 基本数据类型包含了算术类型(arithmetic type)和空类型(void) 算数类型,包含了字符.整型数.布尔值和浮点数 空类型,不对应具体的值 2.1.1 算术类型 算术 ...

  6. 【转】#define 定义别名和 typedef 声明类型的区别

    下面一段程序的执行结果是: #include <stdio.h>#define CHAR2 char*int main(){    typedef char* CHAR;    CHAR ...

  7. Swift声明参考

    一条声明可以在你的程序里引入新的名字和构造.举例来说,你可以使用声明来引入函数和方法,变量和常量,或者来定义 新的命名好的枚举,结构,类和协议类型.你也可以使用一条声明来延长一个已经存在的命名好的类型 ...

  8. Item 13: 比起iterator优先使用const_iterator

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 STL中的const_iterator等价于pointers-to ...

  9. Swift5 语言参考(六) 声明

    一个声明引入了一个新的名称或构建到你的程序.例如,您使用声明来引入函数和方法,引入变量和常量,以及定义枚举,结构,类和协议类型.您还可以使用声明来扩展现有命名类型的行为,并将符号导入到其他地方声明的程 ...

  10. Yii2的深入学习--别名(Aliases)

    在之前自动加载机制的文章中,我们有提到别名,提到 getAlias 方法,大家当时可能不太清楚,这到底是什么,今天我们就来说一下别名. 别名用来表示文件路径和 URL,这样就避免了将一些文件路径.UR ...

随机推荐

  1. <<运算?&=、|=、 ^=、<<=、>>=的意思? 十六进制前缀是 0x。

    <<运算? a<<b 表示把a转为二进制后左移b位(在后面添加 b个0).例如100的二进制表示为1100100,100左移2位后(后面加2个零):1100100<< ...

  2. Spring事务注意事项 以及 遇到的坑

    原创参考: https://www.cnblogs.com/yougewe/p/7466677.html   (Spring,为内部方法新起一个事务,此处应有坑.) https://blog.csdn ...

  3. vant-ui经验

    1.van-checkbox搭配van-cell使用,点击圆圈区域,不触发定义的click函数. 解决:给van-checkbox添加一层div,添加click事件:van-checkbox也添加cl ...

  4. viewpager加fragment可滑动加radio跟随滑动

    public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener, V ...

  5. 95、linux安装es

    参考大佬文章 https://blog.csdn.net/b13001216978/article/details/110817204 1.由于elasticsearch7.4.0需要jdk11支持, ...

  6. 02、kafka介绍

    001.kafka简介 kafka消息队列有两种消费模式,分别是点对点模式和订阅/发布模式.具体比较可以参考Kafka基础–消息队列与消费模式. 下图是一个点对点的Kafka结构示意图 produce ...

  7. css3字体颜色渐变

    效果图: 代码: <span class="titleName">这是个测试字体</span> .titleName { background: linea ...

  8. VUE学习-基础(基础语法 & 模板语法)

    基础语法 引入vue <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/ ...

  9. Taro 弹窗阻止小程序滑动穿透(亲测有效) tabbar数据缓存不更新 入口场景值不同

    v3.0 推出后反馈最多的问题之一,就是在 touchmove 事件回调中调用 e.stopPropagation() 并不能阻止滑动穿透. 这是因为 Taro 3 的事件冒泡机制是单独在小程序逻辑层 ...

  10. 关于 java 上传,下载和导入报java.lang.IllegalStateException异常解决办法

    java.lang.IllegalStateException异常解决办法  最近在使用response.sendRedirect()时出现如下错误:java.lang.IllegalStateExc ...