一、long long类型
新增了类型long long和unsigned long long,以支持64位(或更宽)的整型。
在VS中,int和long都是4字节,long long是8字节。
在Linux中,int是4字节,long和long long是8字节。
二、char16_t和char32_t类型
新增了类型char16_t和char32_t,以支持16位和32位的字符。
意义不大,好像没什么人用,连demo程序都找不到。
三、原始字面量
在《45、C++11的原始字面量》中有详细介绍。
四、统一的初始化(列表)
C++11丰富了大括号的使用范围,用大括号括起来的列表(统一的初始化列表)可以用于所有内置类型和用户自定义类型。使用统一的初始化列表时,可以添加等号(=),也可以不添加:
int x={5};
double y{2.75};
short quar[5]{4,5,2,76,1};
统一的初始化列表也可以用于new表达式中:
int *ar=new int[4]{2,4,6,7};
创建对象时,也可以使用大括号(而不是圆括号)来调用构造函数:
class Girl
{
private:
int m_bh;
string m_name;
public:
Girl(int bh,string name) : m_bh(bh),m_name(name) {}
};
Girl g1(3, "西施"); // C++98的风格。
Girl g2={5, "冰冰"}; // C++11的风格。
Girl g3{8, "幂幂"}; // C++11的风格。
STL容器提供了将initializer_list模板类作为参数的构造函数:
vector v1(10); // 把v1初始化为10个元素。
vector v2{10}; // 把v2初始化为1个元素,这个元素的值是10。
vector v2{3,5,8}; // 把v3初始化为3个元素,值分别是3、5、8。
头文件提供了对模板类initializer_list的支持,这个类包含成员函数begin()和end()。除了用于构造函数外,还可以将initializer_list用于常规函数的参数:
#include
#include
double sum(std::initializer_list il)
{
double total = 0;
for (auto it = il.begin(); it != il.end(); it++)
total = total + *it;
return total;
}
int main()
{
// double total = sum( 3.14, 5.20, 8 ); // 错误,如果没有大括号,这是三个参数。
double total = sum({ 3.14, 5.20, 8 }); // 正确,有大括号,这是一个参数。
std::cout
}
五、自动推导类型auto
在《140、自动推导类型auto》中有详细介绍。
六、decltype关键字
在《146、函数模板高级》中有详细介绍。
七、函数后置返回类型
在《146、函数模板高级》中有详细介绍。
八、模板的别名
九、空指针nullptr
空指针是不会指向有效数据的指针。以前,C/C++用0表示空指针,这带来了一些问题,这样的话0既可以表示指针常量,又可以表示整型常量。
C++11新增了关键字nullptr,用于表示空指针;它是指针类型,不是整型类型。
为了向后兼容,C++11仍允许用0来表示空指针,因此表达式nullptr==0为true。
使用nullptr提供了更高的类型安全。例如,可以将0传递给形参为int的函数,但是,如果将nullptr传递给这样的函数,编译器将视为错误。
因此,出于清晰和安全考虑,请使用nullptr。
十、智能指针
在《193、智能指针unique_ptr》至《196、智能指针weak_ptr》中有详细介绍。
十一、异常规范方面的修改
在《209、C++异常》中有详细介绍。
十二、强类型枚举(枚举类)
传统的C++枚举提供了一种创建常量的方式,但类型检查比较低级。还有,如果在同一作用域内定义的两个枚举,它们的成员不能同名。
针对枚举的缺陷,C++11 标准引入了枚举类,又称强类型枚举。
声明强类型枚举非常简单,只需要在enum后加上关键字 class。
例如∶
enum e1{ red, green };
enum class e2 { red, green, blue };
enum class e3 { red, green, blue, yellow };
使用强类型枚举时,要在枚举成员名前面加枚举名和::,以免发生名称冲突,如:e2::red,e3::blue
强类型枚举默认的类型为int,也可以显式地指定类型,具体做法是在枚举名后面加上:type,type可以是除wchar_t以外的任何整型。
例如:
enum class e2:char { red, green, blue };
十三、explicit关键字
C++支持对象自动转换,但是,自动类型转换可能导致意外。为了解决这种问题,C++11引入了explicit关键字,用于关闭自动转换的特性。
在《121、自动类型转换》中有详细介绍。
十四、类内成员初始化
在类的定义中初始化成员变量。
class Girl
{
private:
int m_bh=20; // 年龄。
string m_name="美女"; // 姓名。
char m_xb = 'X'; // 性别。
public:
Girl(int bh, string name) : m_bh(bh), m_name(name) {}
};
十五、基于范围的for循环
在《184、基于范围的for循环》中有详细介绍。
十六、新的STL容器
1)array(静态数组)
array的大小是固定的,不像其它的模板类,但array有begin()和end()成员函数,程序员可以array对象使用STL算法。
2)forward_list(单向链表)
3)unordered_map、unordered_multimap、unordered_set、unordered_multiset(哈希表)
十七、新的STL方法(成员函数)
1)C++11新增了的方法cbegin()、cend()、crbegin()、crend(),这些方法将元素视为const。
2)iterator emplace (iterator pos, …); // 在指定位置插入一个元素,…用于构造元素,返回指向插入元素的迭代器。
3)更重要的是,除了传统的拷贝构造函数和赋值函数,C++11新增了移动构造函数和移动赋值函数。
十八、摒弃export
C++98新增了export关键字,C++11不再使用,但仍保留它作为关键字,供以后使用。
十九、嵌套模板的尖括号
为了避免与运算符>>混淆,C++要求在声明嵌套模板时使用空格将尖括号分开:
vector > v1; // 两个>之间必须加空格。
C++11不再这样要求:
vector> v2; // 两个>之间不必加空格。
二十、final关键字
final关键字用于限制某个类不能被继承,或者某个虚函数不能被重写。
final关键字放在类名或虚函数名的后面。
示例:
class AA
{
public:
virtual void test()
{
cout
}
};
class BB : public AA
{
public:
void test() final // 如果有其它类继承BB,test()方法将不允许重写。
{
cout
}
};
class CC : public BB
{
public:
void test() // 错误,BB类中的test()后面有final,不允许重写。
{
cout
}
};
二十一、override关键字
在派生类中,把override放在成员函数的后面,表示重写基类的虚函数,提高代码的可读性。
在派生类中,如果某成员函数不是重写基类的虚函数,随意的加上override关键字,编译器会报错。
示例:
class AA
{
public:
virtual void test()
{
cout
}
};
class BB : public AA
{
public:
void test() override
{
cout
}
};
二十二、数值类型和字符串之间的转换
传统方法用sprintf()和snprintf()函数把数值转换为char*字符串;用atoi()、atol()、atof()把char*字符串转换为数值。
C++11提供了新的方法,在数值类型和string字符串之间转换。
1、数值转换为字符串
使用to_string()函数可以将各种数值类型转换为string字符串类型,这是一个重载函数,在头文件 中声明,函数原型如下:
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
2、字符转换为串数值
在C++中,数值类型包括整型和浮点型,针对于不同的数值类型提供了不同的函数在头文件 中声明,函数原型如下:
int stoi( const string& str, size_t* pos = nullptr, int base = 10 );
long stol( const string& str, size_t* pos = nullptr, int base = 10 );
long long stoll( const string& str, size_t* pos = nullptr, int base = 10 );
unsigned long stoul( const string& str, size_t* pos = nullptr, int base = 10 );
unsigned long long stoull( const string& str, size_t* pos = nullptr, int base = 10 );
float stof( const string& str, size_t* pos = nullptr );
double stod( const string& str, size_t* pos = nullptr );
long double stold( const string& str, size_t* pos = nullptr );
形参说明:
str:需要要转换的string字符串。
pos:传出参数,存放从哪个字符开始无法继续解析的位置,例如:123a45, 传出的位置将为3。
base:若base为0,则自动检测数值进制:若前缀为0,则为八进制,若前缀为0x或0X,则为十六进制,否则为十进制。
注意:string字符串转换为数值的函数可能会抛出异常,在《209、C++异常》中有详细介绍。
示例:
string str="123a45";
size_t pos;
int val = stoi(str, &pos, 10);
cout
cout
二十三、静态断言static_assert
在《210、C++断言》中有详细介绍。
二十四、常量表达式constexpr关键字
const关键字从功能上来说有双重语义:只读变量和修饰常量。
示例:
void func(const int len1)
{
// len1是只读变量,不是常量。
int array1[len1]={0}; // VS会报错,Linux平台的数组长度支持变量,不会报错。
const int len2 = 8;
int array2[len2]={0}; // 正确,len2是常量。
}
C++11标准为了解决const关键字的双重语义问题,保留了const表示“只读”的语义,而将“常量”的语义划分给了新添加的constexpr关键字。
所以,C++11 标准中,建议将const和constexpr的功能区分开,表达“只读”语义的场景用const,表达“常量”语义的场景用constexpr。
二十五、默认函数控制=default与=delete
在C++中自定义的类,编译器会默认生成一些成员函数:
l 无参构造函数
l 拷贝构造函数
l 拷贝赋值函数
l 移动构造函数
l 移动赋值函数
l 析构函数
=default表示启用默认函数。
=delete表示禁用默认函数。
示例:
#include
using namespace std;
class Girl
{
private:
int m_bh = 20; // 年龄。
string m_name = "美女"; // 姓名。
char m_xb = 'X'; // 性别。
public:
Girl() = default; // 启用默认构造函数。
Girl(int bh, string name) : m_bh(bh), m_name(name) {}
Girl(const Girl& g) = delete; // 删除拷贝构造函数。
void show() { cout
};
int main()
{
Girl g1;
g1.show();
// Girl g2 = g1; // 错误,拷贝构造函数已删除。
}