从C++出来到现在已经13年了。
Bjarne Stroustrup(C++的创造者)最近评价C++:”感觉像个新的语言“。
事实上,C++11核心已经发生了很重大的变化:
. 支持Lambda表达式( lambda expressions)
. 对象自动类型推导(automatic type deduction of objects)
. 统一初始化语法(uniform initialization syntax)
. 代理构造(delegating constructors)
. deleted 和defaulted函数声明(deleted and defaulted function declarations)
. 空指针(nullptr)
. 右值引用(rvalue references)
. ... C++11的标准库也已经修订,使用了新的算法,新的容器类,原子操作,类型,
正则表达式,智能指针, async() 功能,及多线程库。 关于C++11核心和库的新特性的完整描述,请见以下网址:
http://www2.research.att.com/~bs/C++0xFAQ.html . Lambda表达式(Lambda Expressions)
Lambda表达式允许你在本地定义函数,即在调用的地方定义, 从而消除函数对象产生的许多安全风险,Lambda表达式的格式如下: [capture](parameters)->return-type {body}
[]里是函数调用的参数列表,表示一个Lambda表达式的开始, 让我们来看一个Lambda例子: 假 设你想计算某个字符串包含多少个大写字母,使用for_each()遍历一个char数组, 下面的Lambda表达式确定每个字母是否是大写字母,每当它 发现一个大写字母, Lambda表达式给Uppercase加1,Uppercase是定义在Lambda表达式外的一个变量: int main()
{
char s[]="Hello World!";
int Uppercase = ; //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将通过值传递,C++ Lambda表达式也包括成员函数构造器。 . 自动类型推导和声明类型(decltype) 在C++03中,在声明对象时,你必须指定对象的类型,然而,在许多情况下, 对象声明时都有初始化,C++11利用了这个优势,允许你声明对象时不指定类型: auto x=; // x has type int because 0 is int
auto c='a'; // char
auto d=0.5; // double
auto national_debt=14400000000000LL; //long long
自动类型推导主要用于对象类型很长很麻烦的时候,或者是对象是自动生成的
时候(使用模板时)
考虑下面迭代器的声明: void fucn(const vector<int> &vi)
{
vector<int>::const_iterator ci=vi.begin();
}
有了自动类型推导后,你可以这样声明:
auto ci=vi.begin(); // 哈哈,省事了
关 键字auto不是什么新生事物,我们早已认识,它实际上可以追溯到前ANSI C时代, 但是,C++11改变了它的含义,auto不再指定自动存储类型对象,相反,它声明的对象 类型是根据初始化代码推断而来的,C++11删除了 auto关键字的旧有含义以避免混淆。 注意了:auto已经不再是当年的auto了! C++11提供了一个类似的机制捕捉对象或表达式的类型,新的操作符decltype需要一个 表达式,并返回它的类 型。 const vector<int> vi; typedef decltype (vi.begin()) CIT; CIT another_const_iterator;
. 统一初始化语法(uniform initialization syntax)
C++至少有4个不同的初始化符号,有些存在重叠, 括号初始化语法如下: std::string s("hello");
int m=int(); //default initialization
在某些情况下,你也可以使用“=”符号进行初始化: std::string s="hello";
int x=;
对于POD聚合,你还可以使用大括号: int arr[]={,,,};
struct tm today={};
最后,构造函数使用成员进行初始化: struct S {
int x;
S(): x() {}
};
显然,这么多种初始化方法会引起混乱,对新手来说就更痛苦了,更糟糕的是, 在C++03中,你不能初始化POD数组成员,POD数组使用new[]分配, C++11使用统一的大括号符号清理了这一混乱局面。 class C {
int a;
int b;
public:
C(int i, int j);
};
C c {,}; //C++11 only. Equivalent to: C c(0,0);
int* a = new int[] { , , }; //C++11 only
class X {
int a[];
public:
X() : a{,,,} {} //C++11, member array initializer
};
对于容器,你可以和一长串的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支持成员在类内初始化: class C { int a=; //C++11 only 这和Java一样 public: C(); }; . 代理构造(delegating constructors) 在C++11中,构造函数可以调用类中的其它构造函数: class M //C++11 delegating constructors
{
int x, y;
char *p;
public:
M(int v) : x(v), y(), p(new char [MAX]) {} //#1 target
M(): M() {cout<<"delegating ctor"<
构造函数#,代理构造函数,调用目标构造函数#。 . deleted 和defaulted函数声明(deleted and defaulted function declarations) 一个结构体中的函数: struct A {
A()=default; //C++11
virtual ~A()=default; //C++11
};
对于被称为defaulted的函数,“=default;”部分告诉编译器为函数生成默认实现。 Defaulted函数有两个好处:比手工实现更高效,让程序员摆脱了手工定义这些函数的麻烦事。 与defaulted函数相反的是deleted函数: int func()=delete;
Deleted函数对防止对象复制很有用,回想一下C++自动为类声明一个拷贝构造函数和一个赋值操作符, 要禁用拷贝,声明这两个特殊的成员函数为=delete即可: struct NoCopy {
NoCopy & operator =( const NoCopy & ) = delete;
NoCopy ( const NoCopy & ) = delete;
};
NoCopy a;
NoCopy b(a); //compilation error, copy ctor is deleted . 空指针(nullptr) 终于,C++有了一个指定空指针常量的关键字,nullptr取代了有错误倾向的NULL宏和0, 这两个空指针替代品已经使用很多年了,nullptr是一个强类型: void f(int); //#1
void f(char *); //#2
//C++03
f(); //which f is called? 0可能是int,也可能是空指针,调谁?
//C++11
f(nullptr) //unambiguous, calls #2 这下好了,空指针只能是nullptr。
nullptr适用于所有指针类别,包括函数指针和成员指针: const char *pc=str.c_str(); //data pointers
if (pc!=nullptr)
cout<<pc<<endl;
int (A::*pmf)()=nullptr; //pointer to member function
void (*pmf)()=nullptr; //pointer to function . 右值引用(rvalue references) C++03中的引用类型只能绑定左值,C++11引入了一种新的引用类型,叫做右值引用,
右值引用可以绑定右值,例如,临时对象和字符串。
增加右值 引用的主要原因是移动语义(move semantics),与传统的复制不一样,
移动意味着目标对象偷窃了源对象的资源, 留下一个状态为“空”的源对象。
在某些情况下,复制 一个对象既代价高又没有必要,这时可以用一个移动操作代替。
如果你想评估移动语义(move semantics)带来的性能收益,可以考虑字符串交换,
一个幼稚的实现如下:
void naiveswap(string &a, string & b)
、 {
string temp = a;
a=b;
b=temp;
}
这样的代价很高,复制字符串必须分配原始内存,将字符从源拷贝到目标。 相反,移动字符串仅仅是交换两个数据成员,不用分配内存,拷贝char数组和删除内存: void moveswapstr(string& empty, string & filled) { //pseudo code, but you get the idea size_t sz=empty.size(); const char *p= empty.data(); //move filled's resources to empty empty.setsize(filled.size()); empty.setdata(filled.data()); //filled becomes empty filled.setsize(sz); filled.setdata(p); } 如果你实现的类支持移动,你可以像以下那样声明一个移动构造函数和一个移动赋值操作符: class Movable
{
Movable (Movable&&); //move constructor
Movable&& operator=(Movable&&); //move assignment operator
};
C++11标准库广泛的使用了移动语义,许多算法和容器都为移动做了优化。

c++11新特性(了解)的更多相关文章

  1. C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)

    因为偶然的机会,在图书馆看到<深入理解C++ 11:C++11新特性解析和应用>这本书,大致扫下,受益匪浅,就果断借出来,对于其中的部分内容进行详读并亲自编程测试相关代码,也就有了整理写出 ...

  2. C++11新特性总结 (二)

    1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; ...

  3. C++11新特性总结 (一)

    1. 概述 最近在看C++ Primer5 刚好看到一半,总结一下C++11里面确实加了很多新东西,如果没有任何了解,别说自己写了,看别人写的代码估计都会有些吃力.C++ Primer5是学习C++1 ...

  4. C++ 11 新特性

    C++11新特性:          1.auto          2.nullptr          3.for          4.lambda表达式          5.override ...

  5. [转载] C++11新特性

    C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...

  6. 在C++98基础上学习C++11新特性

    自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...

  7. C++11新特性——range for

    很多编程语言都有range for语法功能,自C++11起,终于将这个重要功能加入C++标准中.range for语句,可以方便的遍历给定序列中的每个元素并对其执行某种操作. 1.基本语法 for(d ...

  8. C++11新特性——大括号初始化

    C++11之前,C++主要有以下几种初始化方式: //小括号初始化 string str("hello"); //等号初始化 string str="hello" ...

  9. C++11新特性之六——元编程

    C++11新特性之六——元编程

  10. C++11新特性之一——Lambda表达式

    C++11新特性总结可以参考:http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html#section_6.8 C++ ...

随机推荐

  1. Ubuntu优化-py用机器

    关闭防火墙 ufw disable pip换源 yum install python-pip -y mkdir ~/.pip cat > pip.conf<<a [global] i ...

  2. VMware 不可恢复错误(svga)”解决方法

    虚拟机VMware 文件在迁移到另一台计算机时出现"VMware Workstation 不可恢复错误(svga)"  将另一台机器的 VMware 文件拷贝至本机,打开虚拟机出现 ...

  3. C# 类型运算符重载在类继承中的调用测试

    这是一篇晦涩难懂的片面的研究 一,简单的继承层次 class CA { } class CB : CA{ } class CC : CB{ } } void Test(CA oa){//CATest ...

  4. Vim中split的使用方法

    Vim中split的使用方法 一.作用 用split可以显示两个不同的文件:或者同时显示一个文件的两个不同地方:又或者并排比较两个文件.这一切都可以通过分割窗口实现.如下图,左边的两个窗口是mytoo ...

  5. 基于IHttpAsyncHandler的UDP收发器

    很难把UDP和Asp.net扯到一起,但是由于最近项目中需要通过网页发送控制指令到中间件,再由中间件发送到下位机的需求.所以就研究了一下是否可以通过asp.net操控UDP Socket实现数据的收发 ...

  6. 20135316王剑桥 linux第二周课实验笔记

    Linux中命令格式为: command [options选项] [arguments参数] //中括号代表是可选的,即有些命令不需要选项也不需要参数 ls或ls .显示是当前目录的内容,这里“.”就 ...

  7. iOS 后台运行 类型

    iOS后台运行,需要有特定的类型才可以进行.这些内容并不是一直不变的,苹果也在逐步的更新这些内容. 本文内容是2015年11月03日时苹果支持的后台运行类型. 这是官方连接地址 其中较为重要的是下面这 ...

  8. http请求过程简要

    一次http请求主要分为3个大步. 建立tcp连接. 这里就发生了经典的tcp三次握手.做个类比解释下,tcp好比http的秘书,和厂家(服务器端)做买卖.老板(http)叫秘书(tcp)去联系一下, ...

  9. [USACO2003][poj2185]Milking Grid(kmp的next的应用)

    题目:http://poj.org/problem?id=2185 题意:就是要求一个字符矩阵的最小覆盖矩阵,可以在末尾不完全重合(即在末尾只要求最小覆盖矩阵的前缀覆盖剩余的尾部就行了) 分析: 先看 ...

  10. angular_$attrs

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...