Modern C++ 学习笔记——易用性改进篇

C++11之后引入了大量语法糖,这简直就是开发人员的福音,本文介绍了其中部分最为关键的语法糖,建议收藏~~~!!!ModernC++学习笔记是一系列介绍现代C++新特性的文章,结合《effective modern C++》说明了如何更好的使用这些新特性。相互讨论,共同学习,不断成长
摘要由CSDN通过智能技术生成

往期精彩:

Modern C++ 学习笔记——易用性改进篇

关键字:自动类型推导、初始化、字面量

自动类型推导

auto

自动类型推导,就是编译器能够更加表达式的类型,自动决定变量的类型,从C++14开始,还有函数的返回类型。但需要说明的是,auto并没有改变C++是静态语言这一事实。使用auto的变量类型仍然是编译时就确定了,只不过编译器能自动帮你填充而已。有了自动类型推导使得如下赘述称为历史

for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
    // 成为历史
    // 循环体
}
for (auto it = v.begin(); it != end(); ++it) {
    // 现在可以直接这么写,当然,是不使用基于范围的for循环的情况
    // 循环体
}

不使用自动类型推导时,若容器类型未知,还需要加上typename.

template <typename T>
void foo(const T& container) // 此处const引用还要求const_iterator作为迭代器的类型
{
   
    for (typename T::const_iterator it = container.begin(); it != container.end(); ++it) {
   
        // 循环体
    }
}

此外,如果begin返回的类型不是该类型的const_iterator嵌套类型的话,那实际上不用自动类型推断就没法表达了。举个例子,若我们的遍历函数还要求支持C数组的话,不使用自动类型推断就只能在上述代码增加一个对应的重载函数:

template <typename T, size_t N>
void foo(const T (&a)[N]) // 此处const引用还要求const_iterator作为迭代器的类型
{
   
    typedef const T* ptr;
    for (ptr it = container.begin(); it != a + N; ++it) {
   
        // 循环体
    }
}

如果使用自动类型推导,并且再加上C++11提供的begin和end函数,上面的代码就以统一了:

template <typename T>
void foo(const T& c)
{
   
    using std::begin;
    using std::end; // 使用依赖参数查找(ADL)见[1]
    for (auto it = begin(c); it != end(c); ++it) {
   
    // 循环体
    }
}

从这个例子来看,自动类型推导不仅降低了代码的啰嗦程度,也提高了代码的抽象性。
你以为auto带来只是有这些可就错了,它带来的好处远远不止如此:

  • 用auto声明的变量,其型别都推导自其初始化物,所以他们必须初始化:
int x1; // 存在潜在的未初始化风险
auto x2; // 编译错误!必须有初始化物
auto x3 = 0; // 没问题
  • auto可以避免一类称为“型别捷径”的问题,其中潜在存在性能问题,没错就是性能问题。不太相信?那就继续往下看:
std::unordered_map<std::string, int> m;
...
for (const std::pair<std::string, int> &p : m) {
   
    // 在p上实施某些操作
}

似乎,这块代码看起来合情合理。单其中暗藏隐患。原因是std::unordered_map的键值部分是const,所以哈希表中的std::pair(也就是std::unordered_map本身)的型别并不是std::pair(std::string, int),而是std::pair(const std::string, int).
可是在上面的循环中用以声明变量p的类型并不是这个。结果编译器为了将std::pair对象转换为std::pair对象,将m中的每个对象都做了一次复制操作,形成一个p想要绑定的临时对象。循环的每次迭代结束时,该临时对象都会被析构一次。

使用auto就可以轻松化解:

unordered_map<std::string, int> m{
   {
   "hello", 12}};
cout << &(*(m.begin())) << endl; 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值