C++11中值得关注的几大变化 .
Lambda 表达式
Lambda 表达式的形式是这样的:
- [capture](parameters)->return-type {body}
[capture](parameters)->return-type {body}
来看个计数某个字符序列中有几个大写字母的例子:
- int main()
- {
- char s[]="Hello World!";
- int Uppercase = 0; //modified by the lambda
- for_each(s, s+sizeof(s), [&Uppercase] (char c) {
- if (isupper(c))
- Uppercase++;
- });
- cout<< Uppercase<<" uppercase letters in: "<< s<<endl;
- }
int main() { char s[]="Hello World!"; int Uppercase = 0; //modified by the lambda for_each(s, s+sizeof(s), [&Uppercase] (char c) { if (isupper(c)) Uppercase++; }); cout<< Uppercase<<" uppercase letters in: "<< s<<endl; }
其中 [&Uppercase] 中的 & 的意义是 lambda 函数体要获取一个 Uppercase 引用,以便能够改变它的值,如果没有 &,那就 Uppercase 将以传值的形式传递过去。
自动类型推导和 decltype
在 C++03 中,声明对象的同时必须指明其类型,其实大多数情况下,声明对象的同时也会包括一个初始值,C++11 在这种情况下就能够让你声明对象时不再指定类型了:
- auto x=0; //0 是 int 类型,所以 x 也是 int 类型
- auto c='a'; //char
- auto d=0.5; //double
- auto national_debt=14400000000000LL;//long long
auto x=0; //0 是 int 类型,所以 x 也是 int 类型 auto c='a'; //char auto d=0.5; //double auto national_debt=14400000000000LL;//long long
这个特性在对象的类型很大很长的时候很有用,如:
- void func(const vector<int> &vi)
- {
- vector<int>::const_iterator ci=vi.begin();
- }
void func(const vector<int> &vi) { vector<int>::const_iterator ci=vi.begin(); }
那个迭代器可以声明为:
- auto ci=vi.begin();
auto ci=vi.begin();
C++11 也提供了从对象或表达式中“俘获”类型的机制,新的操作符 decltype 可以从一个表达式中“俘获”其结果的类型并“返回”:
- const vector<int> vi;
- typedef decltype (vi.begin()) CIT;
- CIT another_const_iterator;
const vector<int> vi; typedef decltype (vi.begin()) CIT; CIT another_const_iterator;
统一的初始化语法
C++ 最少有 4 种不同的初始化形式,如括号内初始化,见:
- std::string s("hello");
- int m=int(); //default initialization
std::string s("hello"); int m=int(); //default initialization
还有等号形式的:
- std::string s="hello";
- int x=5;
std::string s="hello"; int x=5;
对于 POD 集合,又可以用大括号:
- int arr[4]={0,1,2,3};
- struct tm today={0};
int arr[4]={0,1,2,3}; struct tm today={0};
最后还有构造函数的成员初始化:
- struct S {
- int x;
- S(): x(0) {} };
struct S { int x; S(): x(0) {} };
这么多初始化形式,不仅菜鸟会搞得很头大,高手也吃不消。更惨的是 C++03 中居然不能初始化 POD 数组的类成员,也不能在使用 new[] 的时候初始 POD 数组,操蛋啊!C++11 就用大括号一统天下了:
- class C
- {
- int a;
- int b;
- public:
- C(int i, int j);
- };
- C c {0,0}; //C++11 only. 相当于 C c(0,0);
- int* a = new int[3] { 1, 2, 0 }; /C++11 only
- class X {
- int a[4];
- public:
- X() : a{1,2,3,4} {} //C++11, 初始化数组成员
- };
class C { int a; int b; public: C(int i, int j); }; C c {0,0}; //C++11 only. 相当于 C c(0,0); int* a = new int[3] { 1, 2, 0 }; /C++11 only class X { int a[4]; public: X() : a{1,2,3,4} {} //C++11, 初始化数组成员 };
还有一大好事就是对于容器来说,终于可以摆脱 push_back() 调用了,C++11中可以直观地初始化容器了:
- // C++11 container initializer
- vector vs<string>={ "first", "second", "third"};
- map singers =
- { {"Lady Gaga", "+1 (212) 555-7890"},
- {"Beyonce Knowles", "+1 (212) 555-0987"}};
// C++11 container initializer vector vs<string>={ "first", "second", "third"}; map singers = { {"Lady Gaga", "+1 (212) 555-7890"}, {"Beyonce Knowles", "+1 (212) 555-0987"}};
而类中的数据成员初始化也得到了支持:
- class C
- {
- int a=7; //C++11 only
- public:
- C();
- };
class C { int a=7; //C++11 only public: C(); };
deleted 函数和 defaulted 函数
像以下形式的函数:
- struct A
- {
- A()=default; //C++11
- virtual ~A()=default; //C++11
- };
struct A { A()=default; //C++11 virtual ~A()=default; //C++11 };
叫做 defaulted 函数,=default; 指示编译器生成该函数的默认实现。这有两个好处:一是让程序员轻松了,少敲键盘,二是有更好的性能。
与 defaulted 函数相对的就是 deleted 函数:
- int func()=delete;
int func()=delete;
这货有一大用途就是实现 noncopyabe 防止对象拷贝,要想禁止拷贝,用 =deleted 声明一下两个关键的成员函数就可以了:
- struct NoCopy
- {
- NoCopy & operator =( const NoCopy & ) = delete;
- NoCopy ( const NoCopy & ) = delete;
- };
- NoCopy a;
- NoCopy b(a); //编译错误,拷贝构造函数是 deleted 函数
struct NoCopy { NoCopy & operator =( const NoCopy & ) = delete; NoCopy ( const NoCopy & ) = delete; }; NoCopy a; NoCopy b(a); //编译错误,拷贝构造函数是 deleted 函数
nullptr
nullptr 是一个新的 C++ 关键字,它是空指针常量,它是用来替代高风险的 NULL 宏和 0 字面量的。nullptr 是强类型的:
- void f(int); //#1
- void f(char *);//#2
- //C++03
- f(0); //调用的是哪个 f?
- //C++11
- f(nullptr) //毫无疑问,调用的是 #2
void f(int); //#1 void f(char *);//#2 //C++03 f(0); //调用的是哪个 f? //C++11 f(nullptr) //毫无疑问,调用的是 #2
所有跟指针有关的地方都可以用 nullptr,包括函数指针和成员指针:
- const char *pc=str.c_str(); //data pointers
- if (pc!=nullptr)
- cout<<pc<<endl;
- int (A::*pmf)()=nullptr; //指向成员函数的指针
- void (*pmf)()=nullptr; //指向函数的指针
const char *pc=str.c_str(); //data pointers if (pc!=nullptr) cout<<pc<<endl; int (A::*pmf)()=nullptr; //指向成员函数的指针 void (*pmf)()=nullptr; //指向函数的指针
委托构造函数
C++11 中构造函数可以调用同一个类的另一个构造函数: http://www.xmhlweb.com/
- class M //C++11 delegating constructors
- {
- int x, y;
- char *p;
- public:
- M(int v) : x(v), y(0), p(new char [MAX]) {} //#1 target
- M(): M(0) {cout<<"delegating ctor"<<end;} //#2 delegating
class M //C++11 delegating constructors { int x, y; char *p; public: M(int v) : x(v), y(0), p(new char [MAX]) {} //#1 target M(): M(0) {cout<<"delegating ctor"<<end;} //#2 delegating
#2 就是所谓的委托构造函数,调用了真正的构造函数 #1。
右值引用
在 C++03 中的引用类型是只绑定左值的,C++11 引用一个新的引用类型叫右值引用类型,它是绑定到右值的,如临时对象或字面量。 http://www.xmhlweb.com/
增加右值引用的主要原因是为了实现 move 语义。与传统的拷贝不同,move 的意思是目标对象“窃取”原对象的资源,并将源置于“空”状态。当拷贝一个对象时,其实代价昂贵且无必要,move 操作就可以替代它。如在 string 交换的时候,使用 move 意义就有巨大的性能提升,如原方案是这样的:
转载于:https://www.cnblogs.com/wxinmylife/archive/2011/10/29/2228463.html
C++11中值得关注的几大变化 .相关推荐
- C++11中值得关注的几大变化
赖勇浩(http://laiyonghao.com) 声明:本文源自 Danny Kalev 在 2011 年 6 月 21 日发表的<The Biggest Changes in C++11( ...
- C++11 中值得关注的几大变化
2019独角兽企业重金招聘Python工程师标准>>> 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 (and ...
- Go 1.8中值得关注的几个变化
http://studygolang.com/articles/9298 本文来自:Tony Bai 感谢作者:bigwhite 查看原文:Go 1.8中值得关注的几个变化 在已经过去的2016年,G ...
- Go 1.16中值得关注的几个变化
辛丑牛年初七开工大吉的日子(2021.2.18),Go核心开发团队为中国Gopher们献上了大礼 - Go 1.16版本正式发布了[1]下载到Go 1.16在各个平台的安装包: 2020年双12,Go ...
- Go 1.9中值得关注的几个变化
原文地址:http://tonybai.com/ Go语言在2016年当选tiobe index的年度编程语言. 转眼间6个月过去了,Go在tiobe index排行榜上继续强势攀升,在最新公布的TI ...
- 【人工智能AI大数据】AI 的未来:ChatGPT 世界中值得关注的 4 大趋势
AI 的未来:ChatGPT 世界中值得关注的 4 大趋势 The future of AI: 4 trends to watch for in a ChatGPT world 目录 AI 的未来:C ...
- 万字长文告诉你Go 1.19中值得关注的几个变化
我们知道Go团队在2015年重新规定了团队发布版本的节奏,将Go大版本的发布频率确定为每年两次,发布窗口定为每年的2月与8月.而实现自举的Go 1.5版本[1]是这一个节奏下发布的第一个版本.一般来说 ...
- MySQL 8 中值得关注的新特性和改进
1. 性能:读/写工作负载.IO 密集型工作负载.以及高竞争("hot spot"热点竞争问题)工作负载. 2. NoSQL:提供 NoSQL 存储功能,目前在 8.0 版本中更大 ...
- 今日互联网关注(写在清明节后):每天都有值得关注的大变化
平时写文章除了写一些观点和专题,接下来最喜欢写的就是这种"关注类文章",原因如下: 1.不需要一个特定主题,不拘泥于某件事 2.无需特定文风,撰写很轻松 3.多日之后可以回过来再 ...
最新文章
- 将页面元素置为不可修改Readonly,所有元素统一修改,统一调用
- 算法笔记-归并算法面试题、逆序数问题
- 白盒测试工具_别再头疼工作效率低!这些超实用的黑盒、白盒测试方法你都用上了吗?...
- Java 集合系列(四)—— ListIterator 源码分析
- Node.js 安装报错提示“The error code is 2503“问题解决方法
- 全球及中国吉他霉素预混剂行业创新现状与可持续发展分析报告2022-2027年版
- Opportunity PRODUCT GUID
- 解决ubuntu下的firefox无法在线播放音频和视频的问题
- Ngnix的日志管理和用定时任务完成日志切割
- dubbo-Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError
- 研究发现,近一半生产容器存在漏洞
- 利用python分析微信聊天记录
- developer.biao.daily.20140628
- 第四章:分支结构程序设计
- press ESC in 1 seconds to skip startup.nsh,any other key to continue
- Typora常用快捷键(仅记录常用功能)
- ajax实现数据库获取select二级联动下拉菜单
- 使用Rust开发编译系统(C以及Rust编译的过程)
- MD软件常见问题解答sp1版
- Line电脑版,whatsapp多开软件
热门文章
- thinkphp 框架自动加载原理_ThinkPHP5分析Part 1 基本框架流程
- 爬虫python编程与cvi编程_与爬虫无关,简单的用python进行科学运算
- linux查看服务器负载均衡,Linux服务器负载均衡LB
- 合并单元格两行_28 HTML5标签学习——table单元格的合并
- 军队可以用oracle,使用Oracle JRockit 提高tomcat性能
- C#调用C++ dll类型对照表汇总
- python多线程内存越要越大_Python 面试:这9个问题你一定要掌握!
- 0x80070003系统找不到指定路径_DeepFaceLab错误:DLL Load failed 找不到指定模块!
- im即时通讯源码_IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)
- 华为抢购助手_就一句话,华为这个智慧办公新物种“有点东西”!