目录
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为 C++11之前的最新C++标准名称。打算5年一个标准,打算07年出一个新标准,但是没有完成,把C++07改名叫C++0x,直到11年完成改名问C++11;相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,有很多新东西,其中也有许多鸡肋语法;C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率。
1.1内置类型的初始化列表
- int main()
- {
- // 内置类型变量
- int x1 = {10};
- int x2{10};
- int x3 = 1+2;
- int x4 = {1+2};
- int x5{1+2};
- // 数组
- int arr1[5] {1,2,3,4,5};
- int arr2[]{1,2,3,4,5};
-
- // 动态数组,在C++98中不支持
- int* arr3 = new int[5]{1,2,3,4,5};
-
- // 标准容器
- vector<int> v{1,2,3,4,5};
- map<int, int> m{{1,1}, {2,2,},{3,3},{4,4}};
- return 0;
- }
1.2自定义类型的列表初始化
1.2.1. 标准库支持单个对象的列表初始化
- class Point
- {
- public:
- Point(int x = 0, int y = 0): _x(x), _y(y)
- {}
- private:
- int _x;
- int _y;
- };
- int main()
- {
- Pointer p{ 1, 2 };
- return 0;
- }
C++98支持数组使用列表初始化 ,C++98不支持构造函数列表初始化
int array1[] = {1,2,3,4,5}; int array2[5] = {0};C++支持构造函数列表初始化
vector<int> v{1,2,3,4,5};
原因:1,2,3,4,5,先隐式构造为initializer_list的一个对象,再调用vector对应的构造函数
容器vector的 initializer_list 构造函数和赋值运算符重载
- Vector(initializer_list
l) - : _capacity(l.size())
- , _size(0)
- {
- _array = new T[_capacity];
- for (auto e : l)
- _array[_size++] = e;
- }
-
- Vector
& operator=(initializer_list l) - {
- delete[] _array;
- size_t i = 0;
- for (auto e : l)
- _array[i++] = e;
- return *this;
- }
C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型(vector,list)和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。
语法2:decltype类型推导
- const int x = 2;
- const int y = 3;
- decltype(x+y) z = 3;
- cout << typeid(z).name() << endl;
1.default:显式缺省函数
写了拷贝构造函数就不会默认生成构造函数了,就没办法创造一个无参的对象了
class Person { public: //person()=default; Person(const char* name,int age) :_name(name) ,_age(age) {} private: string _name; int _age=0; }; int main() { Person p; return 0; }
person()=default ;这句代码就可以让编译器默认生成;
2.delete:删除默认函数,没有办法真正删除,只是不让删除使用
C++98 防拷贝:1、只声明不实现 2、声明成私有
class A { public: A() = default; private: A(const A& a); };
C++11:使用A(const A& a)=delete即可
class A { public: A() = default; A(const A& a)=delete; private: };
这里有一组数据,按名称或者按数量,要怎么办了;
pairint> fruit[] = { {"香蕉",15}, {"菠萝",23},{"柿子",35}, {"芒果",12} };
使用仿函数
- class compareName
- {
- public:
- bool operator()(const pair
int >& l, const pairint >& r) - {
- return l.first <= r.first;
- }
- };
- class compareNumber
- {
- public:
- bool operator()(const pair
int >& l, const pairint >& r) - {
- return l.second <= r.second;
- }
- };
- int main()
- {
- pair
int> fruit[] = { {"香蕉",15}, {"菠萝",23},{"柿子",35}, {"芒果",12} }; - sort(fruit, fruit+ 4, compareNumber());
- for (int i = 0; i < 4; i++)
- {
- cout << fruit[i].second << " ";
- }
- cout << endl;
- sort(fruit, fruit + 4, compareName());
- for (int i = 0; i < 4; i++)
- {
- cout << fruit[i].first << " ";
- }
- }
每次为了实现一个algorithm算法, 都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便;
使用lambda表达式代码就会简短一些
- pair
int> fruit[] = { {"香蕉",15}, {"菠萝",23},{"柿子",35}, {"芒果",12} }; - //数量比较
- sort(fruit, fruit + 4, [](const pair
int>& l, const pairint>& r)->bool - { return l.second <= r.second; });
- for (int i = 0; i < 4; i++)
- {
- cout << fruit[i].second << " ";
- }
- cout << endl;
- //名字比较
- sort(fruit, fruit + 4, [](const pair
int>& l, const pairint>& r)->bool - { return l.first <= r.first;});
- for (int i = 0; i < 4; i++)
- {
- cout << fruit[i].first << " ";
- }
lambda表达式语法:
最简单的一个lambda表达式:[]{};
捕捉列表:该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
- int a = 10;
- int b = 20;
- auto Add = [a, b] {return a + b; };
- cout<<Add();
输出:30;
5种捕捉:所有捕捉的变量都是被const修饰的;加mutable就取消了常性;
实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,只是简短仿函数的写法;