C++11的重大改变

C++11支持lambda表达式,自动类型推断,统一的初始化语法,委托构造函数,删除和默认函数声明,nullptr,以及最重要的右值引用——一种预言将会改变创造和处理对象方式的技术。
C++11标准库同样增加了新的算法,新的容器类,原子运算,类型特性,正则表达式,新的智能指针,async()功能以及多线程库。

自动类型推断auto和decltype

auto c = 'a'; // char
auto d = 0.5; // double
auto national_debt = 14400000000000LL; //long long

C++11 为捕获对象或表达式的类型提供了类似的机制。新的运算符decltype接收一个表达式并“返回”其类型:

const vector<int> vi;
typedef decltype (vi.begin()) CIT;
CIT another_const_iterator;

统一初始化语法
C++至少有四种不同的初始化方法,有些是重叠的。

//带有括号的初始化类似:
std::string s("hello");
int m = int(); // 默认初始化
//在某些特殊情况,你也可以使用“=”达到相同目的:
std::string s = "hello";
int x = 5;
//对于 POD(Plain Old Data,具有 C 兼容特点)聚合,可以使用大括号:
int arr[4] = {0,1,2,3};
struct tm today = {0};
//最后,在构造函数中使用成员初始化器:
struct S
{
    int x;
    S(): x(0) {}
};

C++11使用统一的大括号:

class C
{
    int a;
    int b;
public:
    C(int i, int j);
};

C c {0,0}; // C++11可用,等价于C c(0,0);
int* a = new int[3] { 1, 2, 0 }; // C++11可用
class X
{
    int a[4];
public:
    X() : a{1,2,3,4} {} // C++11 可用,成员数组初始化器
};

//对于容器,现在可以跟一长串push_back()调用说再见了。在C++11你可以直观地初始化容器:
vector<string> vs = { "first", "second", "third"};
map singers = { {"Lady Gaga", "+1 (212) 555-7890"},
                {"Beyonce Knowles", "+1 (212) 555-0987"}};

//类似的,C++11支持数据成员的类内初始化:
class C
{
    int a = 7; // C++11可用
public:
    C();
};

删除和默认函数

struct A
{
    A() = default; // C++11
    virtual ~A() = default; // C++11
};

=default;说明,编译器生成该函数的一个默认实现。默认函数有两个优势:比手工实现更有效;把程序员从手动定义这些函数的繁琐中解放出来。
删除函数:

int func() = delete;

删除函数对防止对象复制很有用。C++为每个类自动声明一个拷贝构造函数和赋值运算符。为禁止复制,需要将这两个特殊的成员函数声明为=delete。

nullptr
终于,C++有了一个代表空指针常量的关键字。nullptr替换了充满bug的NULL宏,以及被用于空指针好多年的字面常量0。nullptr是强类型的:

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(); // 数据指针
if (pc != nullptr)
    cout << pc << endl;

int (A::*pmf)() = nullptr; // 成员函数指针
void (*pmf)() = nullptr; // 函数指针

委托构造函数
在 C++11中,构造函数可以调用同一个类中另外的构造函数:

class M // C++11委托构造函数
{
    int x, y;
    char *p;
public:
    M(int v) : x(v), y(0), p(new char [MAX]) {} // #1 目标
    M(): M(0) {cout << "delegating ctor" << endl;} // #2 委托
};
//构造函数#2是委托构造函数,调用了目标构造函数#1。

右值引用

C++03的引用类型只能绑定左值。C++11引入了新的引用类型——右值引用。右值引用可以绑定右值,例如临时变量和字面常量。
增加右值引用的主要原因是移动语义。在这种情景下,拷贝一个对象既昂贵又不必要,应该使用移动操作符。

void naiveswap(string &a, string & b)
{
    string temp = a;
    a = b;
    b = temp;
}

这种实现很昂贵。拷贝字符串需要分配内存,将字符从源对象复制到目标对象。相比而言,移动字符串仅仅意味着交换两个数据成员,不需要分配内存、复制字符数组和释放内存:

void moveswapstr(string& empty, string & filled)
{
    // 伪代码,体会思想
    size_t sz = empty.size();
    const char *p = empty.data();
    
    // 移动filled的资源到empty
    empty.setsize(filled.size());
    empty.setdata(filled.data());
    
    // 移动empty的资源到filled
    filled.setsize(sz);
    filled.setdata(p);
}

如果你正在实现一个支持移动的类,需要声明一个移动构造函数和移动复制运算符:

class Movable
{
    Movable (Movable&&); // 移动构造函数
    Movable&& operator=(Movable&&); // 移动复制运算符
};

C++11 标准库大量使用了移动语义。许多算法和容器也为移动语义做了优化。
C++11 标准库
2003年,C++以库技术报告 1(TR1)的形式经历了一次大型重构。TR1包含了新的容器类(unordered_set,unordered_map,unordered_multiset和unordered_multimap)和许多新的库,例如正则表达式,元祖,函数对象包装器。下面是C++11标准库的特性:
线程库
毫无疑问,从程序员角度看,C++11最重要的改进就是并发。C++11有一个thread类,描述一个执行线程、promise和future(用于并发环境下同步的对象),用于发起并发任务的模板函数async()和用于声明线程独立的数据的存储类型thread_local。快速了解C++11线程库,请阅读Anthony Williams的文章Simpler Multithreading in C++0x。
新的智能指针类
C++98只定义了一个智能指针类,auto_ptr,而这个类现在已经被废弃了。C++11包含了新的智能指针类:shared_ptr和最近新加的unique_ptr。
新的算法
C++11标准库定义了模拟集合论操作的新的算法all_of()、any_of()和none_of()。下面几行将谓词ispositive()应用于范围[first, first+n),然后使用all_of()、any_of()和none_of()检测范围的属性:

#include <algorithm>
// C++11 代码
// 所有元素都是正数吗?
all_of(first, first+n, ispositive()); // false

// 至少有一个元素是正数吗?
any_of(first, first+n, ispositive()); // true

// 没有元素是正数?
none_of(first, first+n, ispositive()); // false

还有一个新的copy_n算法。

#include <algorithm>

int source[5] = { 0, 12, 34, 50, 80 };
int target[5];
// 从源数组到目的数组拷贝 5 个元素
copy_n(source, 5, target);

C++11依然缺少一些有用的库,例如 XML API,socket,GUI,反射——当然,还有合理的自动垃圾回收器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值