Modern C++——不准确“类型声明”引发的非必要性能损耗

C++是一种强类型语言。我们在编码时就需要明确指出每个变量的类型,进而让编译器可以正确的编译。看似C++编译器比其他弱类型语言的编译器要死板,实则它也做了很多“隐藏”的操作。它会在尝试针对一些非预期类型进行相应转换,以符合预期,比如《C++拾趣——类构造函数的隐式转换》中提到的隐式转换。

但是也正因为这些“隐藏”的转换行为,让一些行为超出我们的预期。比如本文提及的案例,就是因为我们声明了一个不准确的类型变量,导致编译器为了让我们代码“合法”,进而做了一些隐式转换,导致程序性能下降。

我们也将通过这个案例,了解C++11引入auto关键字的必要性。

案例

先看下面这段可以运行的代码。

    std::cout << "Create unordered_map" << std::endl;

    std::unordered_map<Custom, int> unordered_map;
    unordered_map[std::move(Custom(1))] = 1;
    unordered_map[std::move(Custom(2))] = 2;
    unordered_map[std::move(Custom(3))] = 3;

    std::cout << std::endl << "Traverse unordered_map using std::pair<Custom, int>" << std::endl;

    for (const std::pair<Custom, int>& pair : unordered_map) {
        std::cout << pair.first << " " << pair.second << std::endl;
    }

请问下面的代码有什么性能问题?

可能第一眼看过去,并不能发现它的问题所在。我们将这段代码的运行过程打印出来
在这里插入图片描述
可以发现在遍历的过程中,发生了Custom对象的复制和析构。

如果Custom对象比较大,就会引发性能问题。

这是因为std::unordered_map的Key是const类型,即我们应该如下方式遍历

    for (const std::pair<const Custom, int>& pair : unordered_map) {
        std::cout << pair.first << " " << pair.second << std::endl;
    }   

编译器在发现我们没有使用const Custom时,会自己推理并转换以符合我们书写的代码。这样就会导致一次const Custom向Custom复制的一次构造。

正因为这些犄角旮旯的知识导致编写健壮高效的C++代码比较困难。但是在C++11中引入的auto就可以很大的缓解我们的心智负担。我们可以这么写上述代码

    for (const auto& pair : unordered_map) {
        std::cout << pair.first << " " << pair.second << std::endl;
    }

这样编译器会帮我们推导出正确的类型。
在这里插入图片描述

代码地址

https://github.com/f304646673/cpulsplus/tree/master/traverse_unordered_map

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

breaksoftware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值