相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率。
在C++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。
- struct Point
- {
- int _x;
- int _y;
- };
- int main()
- {
- int array1[] = { 1, 2, 3, 4, 5 };
- int array2[5] = { 0 }; //0 0 0 0 0
- Point p = { 1, 2 }; //运用了struct结构体的语法 初始化
- return 0;
- }
C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。
- struct Point
- {
- int _x;
- int _y;
-
- Point(int x, int y)
- :_x(x)
- , _y(y)
- {}
- };
-
- class Date
- {
- public:
- Date(int year, int month, int day)
- :_year(year)
- , _month(month)
- , _day(day)
- {
- cout << "Date(int year, int month, int day)" << endl;
- }
-
- private:
- int _year;
- int _month;
- int _day;
- };
-
-
- int main()
- {
-
- Point p = { 1, 2 };
- //Point p{ 1, 2 };
-
- Point* p3 = new Point[3]{ {1, 1}, { 2, 2 }, { 3, 3 } };
-
- int* p1 = new int(0);
- int* p2 = new int[5]{1,2,3,4,5};
- //C++11中 new可以初始化数组
-
- //自定义类型的列表初始化
- Date d1(2022, 3, 13);
- Date d2 = { 2022, 3, 15 };
- Date d3{ 2022, 3, 15 };
- Date{2022,3,15};
-
- int i = 1;
- int j = { 2 };
- int k{ 3 };
- return 0;
- }
总结:
模拟实现的vector支持{}初始化和赋值:
- template<class T>
- class vector
- {
- public:
- typedef T* iterator;
- vector(initializer_list
l) - {
- _start = new T[l.size()];
- _finish = _start + l.size();
- _endofstorage = _start + l.size();
- iterator vit = _start;
- typename initializer_list
::iterator lit = l.begin(); - while (lit != l.end())
- {
- *vit++ = *lit++;
- }
- //for (auto e : l)
- // *vit++ = e;
- }
- vector
& operator=(initializer_list l) { - vector
tmp(l); - std::swap(_start, tmp._start);
- std::swap(_finish, tmp._finish);
- std::swap(_endofstorage, tmp._endofstorage);
- return *this;
- }
- private:
- iterator _start;
- iterator _finish;
- iterator _endofstorage;
- };
std::initializer_list使用场景:
std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器(像map、vector、list)就增加std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=的参数,这样就可以用大括号赋值
- class A
- {
- public:
- A(int a, double d, int b)
- :_a(a)
- , _d(d)
- , _b(b)
- {}
- private:
- int _a;
- double _d;
- int _b;
- };
- class Date
- {
- public:
- Date(int year, int month, int day)
- :_year(year)
- , _month(month)
- , _day(day)
- {
- cout << "Date(int year, int month, int day)" << endl;
- }
-
- private:
- int _year;
- int _month;
- int _day;
- };
-
- int main()
- {
- //内置类型的列表初始化
- vector<int> v1 = { 1, 2, 3, 4, 5 };
- vector<int> v2{ 1, 2, 3, 4, 5 };
- //vector (initializer_list
il,const allocator_type& alloc = allocator_type()); -
-
- auto lt1 = {1, 2, 3, 4};
- initializer_list<int> lt2 = { 1, 2, 3, 4 };
- //auto=initializer_list
-
-
- map
int> dict1 = { pairint>("sort", 1), pairint>("insert", 2) }; - map
int> dict2 = { { "sort", 1 }, { "insert", 2 } }; - //首先{ "sort", 1 }, { "insert", 2 }创建成initializer_list
- //最后map (initializer_list
il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type()); - //这个构造函数初始化dict2
-
-
- //自定义类型的列表初始化
- Date d1(2022, 3, 13);
- Date d2 = { 2022, 3, 15 };
- Date d3{ 2022, 3, 15 };
- Date{ 2022, 3, 15 };
-
-
-
- A aa1 = { 1, 1.11, 1};
- //首先{ { 1, 1.11, 1}, { 2, 2.22, 1} }创建成initializer_list
>类型的对象(首先是A类得有相应的构造函数才行)
- //最后list的构造函数初始化it
- return 0;
- }
总结:
c++11提供了多种简化声明的方式,尤其是在使用模板时。
在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型
- int main()
- {
- int i = 10;
- auto p = &i;
-
- auto pf = strcpy;
- //输出p、pf的类型
- cout << typeid(p).name() << endl;
- cout << typeid(pf).name() << endl;
-
- map
dict = { {"sort", "排序"}, {"insert", "插入"} }; - //map
::iterator it = dict.begin(); -
- auto it = dict.begin();
-
- return 0;
- }
关键字decltype将变量的类型声明为表达式指定的类型
- // decltype的一些使用使用场景
- template<class T1, class T2>
- void F(T1 t1, T2 t2)
- {
- decltype(t1 * t2) ret = t1 * t2;
- vector<decltype(t1* t2)> v;
- v.push_back(ret);
- cout << typeid(ret).name() << endl;
- }
-
- int main()
- {
- int i = 10;
- auto p = &i;
- auto pf = strcpy;
- decltype(pf) pf1; //char * (__cdecl*)(char *,char const *)
- vector<decltype(pf)> v;
-
- cout << typeid(p).name() << endl;
- cout << typeid(pf).name() << endl;
-
- return 0;
- }
注意:decltype与auto的差别:auto必须要求显式初始化,而decltype没要求
由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示
整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。
- #ifndef NULL
- #ifdef __cplusplus
- #define NULL 0
- #else
- #define NULL ((void *)0)
- #endif
- #endif