C++开发者都应该使用的十个C++11特性(上)
wptr33 2025-06-04 02:12 16 浏览
在C++11新标准中,语言本身和标准库都增加了很多新内容,本文只涉及了一些皮毛。不过我相信这些新特性当中有一些,应该成为所有C++开发者的常规装备。你也许看到过许多类似介绍各种C++11特性的文章。下面是我总结的,C++开发者都需要学习和使用的C++11新特性。
auto
在C++11之前,auto关键字用来指定存储期。在新标准中,它的功能变为类型推断。auto现在成了一个类型的占位符,通知编译器去根据初始化代码推断所声明变量的真实类型。各种作用域内声明变量都可以用到它。例如,名空间中,程序块中,或是for循环的初始化语句中。
123 | auto i = 42; // i is an intauto l = 42LL; // l is an long longauto p = newfoo(); // p is a foo* |
使用auto通常意味着更短的代码(除非你所用类型是int,它会比auto少一个字母)。试想一下当你遍历STL容器时需要声明的那些迭代器(iterator)。现在不需要去声明那些typedef就可以得到简洁的代码了。
1234 | std::map<std::string, std::vector<int>> map;for(auto it = begin(map); it != end(map); ++it){} |
需要注意的是,auto不能用来声明函数的返回值。但如果函数有一个尾随的返回类型时,auto是可以出现在函数声明中返回值位置。这种情况下,auto并不是告诉编译器去推断返回类型,而是指引编译器去函数的末端寻找返回值类型。在下面这个例子中,函数的返回值类型就是operator+操作符作用在T1、T2类型变量上的返回值类型。
123456 | template<typenameT1, typenameT2>auto compose(T1 t1, T2 t2) -> decltype(t1 + t2){returnt1+t2;}auto v = compose(2, 3.14); // v's type is double |
nullptr
以前都是用0来表示空指针的,但由于0可以被隐式类型转换为整形,这就会存在一些问题。关键字nullptr是std::nullptr_t类型的值,用来指代空指针。nullptr和任何指针类型以及类成员指针类型的空值之间可以发生隐式类型转换,同样也可以隐式转换为bool型(取值为false)。但是不存在到整形的隐式类型转换。
123456789101112131415 | voidfoo(int* p) {}voidbar(std::shared_ptr<int> p) {}int* p1 = NULL;int* p2 = nullptr;if(p1 == p2){}foo(nullptr);bar(nullptr);boolf = nullptr;inti = nullptr; // error: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type |
为了向前兼容,0仍然是个合法的空指针值。
Range-based for loops(基于范围的for循环)
为了在遍历容器时支持”foreach”用法,C++11扩展了for语句的语法。用这个新的写法,可以遍历C类型的数组、初始化列表以及任何重载了非成员的begin()和end()函数的类型。
如果你只是想对集合或数组的每个元素做一些操作,而不关心下标、迭代器位置或者元素个数,那么这种foreach的for循环将会非常有用。
12345678910111213141516171819202122 | std::map<std::string, std::vector<int>> map;std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);map["one"] = v;for(constauto& kvp : map){std::cout << kvp.first << std::endl;for(auto v : kvp.second){std::cout << v << std::endl;}}intarr[] = {1,2,3,4,5};for(int& e : arr){e = e*e;} |
Override和final
我总觉得 C++中虚函数的设计很差劲,因为时至今日仍然没有一个强制的机制来标识虚函数会在派生类里被改写。vitual关键字是可选的,这使得阅读代码变得很费劲。因为可能需要追溯到继承体系的源头才能确定某个方法是否是虚函数。为了增加可读性,我总是在派生类里也写上virtual关键字,并且也鼓励大家都这么做。即使这样,仍然会产生一些微妙的错误。看下面这个例子:
1234567891011 | classB{public:virtualvoidf(short) {std::cout << "B::f"<< std::endl;}};classD : publicB{public:virtualvoidf(int) {std::cout << "D::f"<< std::endl;}}; |
D::f 按理应当重写 B::f。然而二者的声明是不同的,一个参数是short,另一个是int。因此D::f(原文为B::f,可能是作者笔误——译者注)只是拥有同样名字的另一个函数(重载)而不是重写。当你通过B类型的指针调用f()可能会期望打印出D::f,但实际上则会打出 B::f 。
另一个很微妙的错误情况:参数相同,但是基类的函数是const的,派生类的函数却不是。
1234567891011 | classB{public:virtualvoidf(int) const{std::cout << "B::f "<< std::endl;}};classD : publicB{public:virtualvoidf(int) {std::cout << "D::f"<< std::endl;}}; |
同样,这两个函数是重载而不是重写,所以你通过B类型指针调用f()将打印B::f,而不是D::f。
幸运的是,现在有一种方式能描述你的意图。新标准加入了两个新的标识符(不是关键字)::
1. override,表示函数应当重写基类中的虚函数。
2. final,表示派生类不应当重写这个虚函数。
第一个的例子如下:
1234567891011 | classB{public:virtualvoidf(short) {std::cout << "B::f"<< std::endl;}};classD : publicB{public:virtualvoidf(int) override {std::cout << "D::f"<< std::endl;}}; |
现在这将触发一个编译错误(后面那个例子,如果也写上override标识,会得到相同的错误提示):
1 | 'D::f' : method with override specifier 'override' did not override any base class methods |
另一方面,如果你希望函数不要再被派生类进一步重写,你可以把它标识为final。可以在基类或任何派生类中使用final。在派生类中,可以同时使用override和final标识。
1234567891011121314151617 | classB{public:virtualvoidf(int) {std::cout << "B::f"<< std::endl;}};classD : publicB{public:virtualvoidf(int) override final {std::cout << "D::f"<< std::endl;}};classF : publicD{public:virtualvoidf(int) override {std::cout << "F::f"<< std::endl;}}; |
被标记成final的函数将不能再被F::f重写。
感谢作者冯上(@治不好你我就不是兽医 ),本文转自伯乐在线
大家如果对编程感兴趣,想了解更多的编程知识,解决编程问题,我们这里有java高手,C++/C高手,windows/Linux高手等,大家关注我的微信公众号:程序员互动联盟or coder_online
相关推荐
- redis的八种使用场景
-
前言:redis是我们工作开发中,经常要打交道的,下面对redis的使用场景做总结介绍也是对redis举报的功能做梳理。缓存Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。...
- 基于Redis的3种分布式ID生成策略
-
在分布式系统设计中,全局唯一ID是一个基础而关键的组件。随着业务规模扩大和系统架构向微服务演进,传统的单机自增ID已无法满足需求。高并发、高可用的分布式ID生成方案成为构建可靠分布式系统的必要条件。R...
- 基于OpenWrt系统路由器的模式切换与网页设计
-
摘要:目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户、提升服务的目标。传统路由器自带的Luci界面提供了工厂模式的Web界面,用户可通过该界面配置路...
- 这篇文章教你看明白 nginx-ingress 控制器
-
主机nginx一般nginx做主机反向代理(网关)有以下配置...
- 如何用redis实现注册中心
-
一句话总结使用Redis实现注册中心:服务注册...
- 爱可可老师24小时热门分享(2020.5.10)
-
No1.看自己以前写的代码是种什么体验?No2.DooM-chip!国外网友SylvainLefebvre自制的无CPU、无操作码、无指令计数器...No3.我认为CS学位可以更好,如...
- Apportable:拯救程序员,IOS一秒变安卓
-
摘要:还在为了跨平台使用cocos2d-x吗,拯救objc程序员的奇葩来了,ApportableSDK:FreeAndroidsupportforcocos2d-iPhone。App...
- JAVA实现超买超卖方案汇总,那个最适合你,一篇文章彻底讲透
-
以下是几种Java实现超买超卖问题的核心解决方案及代码示例,针对高并发场景下的库存扣减问题:方案一:Redis原子操作+Lua脚本(推荐)//使用Redis+Lua保证原子性publicbo...
- 3月26日更新 快速施法自动施法可独立设置
-
2016年3月26日DOTA2有一个79.6MB的更新主要是针对自动施法和快速施法的调整本来内容不多不少朋友都有自动施法和快速施法的困扰英文更新日志一些视觉BUG修复就不翻译了主要翻译自动施...
- Redis 是如何提供服务的
-
在刚刚接触Redis的时候,最想要知道的是一个’setnameJhon’命令到达Redis服务器的时候,它是如何返回’OK’的?里面命令处理的流程如何,具体细节怎么样?你一定有问过自己...
- lua _G、_VERSION使用
-
到这里我们已经把lua基础库中的函数介绍完了,除了函数外基础库中还有两个常量,一个是_G,另一个是_VERSION。_G是基础库本身,指向自己,这个变量很有意思,可以无限引用自己,最后得到的还是自己,...
- China's top diplomat to chair third China-Pacific Island countries foreign ministers' meeting
-
BEIJING,May21(Xinhua)--ChineseForeignMinisterWangYi,alsoamemberofthePoliticalBureau...
- 移动工作交流工具Lua推出Insights数据分析产品
-
Lua是一个适用于各种职业人士的移动交流平台,它在今天推出了一项叫做Insights的全新功能。Insights是一个数据平台,客户可以在上面实时看到员工之间的交流情况,并分析这些情况对公司发展的影响...
- Redis 7新武器:用Redis Stack实现向量搜索的极限压测
-
当传统关系型数据库还在为向量相似度搜索的性能挣扎时,Redis7的RedisStack...
- Nginx/OpenResty详解,Nginx Lua编程,重定向与内部子请求
-
重定向与内部子请求Nginx的rewrite指令不仅可以在Nginx内部的server、location之间进行跳转,还可以进行外部链接的重定向。通过ngx_lua模块的Lua函数除了能实现Nginx...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)