目录
①C++98中,标准允许使用大括号{ }对数组或者结构体元素进行统一的列表初始值设定
- struct Point
- {
- int _x;
- int _y;
- };
-
- int main()
- {
- //使用大括号对数组元素进行初始化
- int array1[] = { 1, 2, 3, 4, 5 };
- int array2[5] = { 0 };
-
- //使用大括号对结构体元素进行初始化
- Point p = { 1, 2 };
- return 0;
- }
②C++11扩大了用大括号括起来的列表 { 初始化列表 }的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号,也可不添加
- struct Point
- {
- int _x;
- int _y;
- };
-
- int main()
- {
- //使用大括号对内置类型进行初始化
- int x1 = { 1 }; //可添加等号
- int x2{ 2 }; //可不添加等号
-
- //使用大括号对数组元素进行初始化
- int array1[]{1, 2, 3, 4, 5}; //可不添加等号
- int array2[5]{0}; //可不添加等号
-
- //使用大括号对结构体元素进行初始化
- Point p{ 1, 2 }; //可不添加等号
-
- //C++11中列表初始化也可以用于new表达式中(C++98无法初始化)
- int* p1 = new int[4]{0}; //不可添加等号
- int* p2 = new int[4]{1,2,3,4}; //不可添加等号
- return 0;
- }
③创建对象时也可以使用列表初始化方式调用构造函数初始化
- 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()
- {
- //一般调用构造函数创建对象的方式
- Date d1(2022, 8, 29);
-
- //C++11支持的列表初始化,这里也会调用构造函数初始化
- Date d2 = { 2022, 8, 30 }; //可添加等号
- Date d3{ 2022, 8, 31 }; //可不添加等号
- return 0;
- }
①C++11中新增了initializer_list容器,该容器没有提供过多的成员函数
②initializer_list本质就是一个大括号括起来的列表,如果用auto关键字定义一个变量来接收一个大括号括起来的列表,然后以 typeid(变量名).name() 的方式查看该变量的类型,此时会发现该变量的类型就是initializer_list。
- int main()
- {
- auto il = { 1, 2, 3, 4, 5 };
- cout << typeid(il).name() << endl; //class std::initializer_list
- return 0;
- }
③initializer_list的使用场景
- 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> v = { 1, 2, 3, 4, 5 };
- list<int> l = { 10, 20, 30, 40, 50 };
- vector
vd = { Date(2022, 1, 1), Date{ 2022, 2, 2}, { 2022, 3, 3 } }; - map
m{ make_pair("sort", "排序"), { "insert", "插入" } }; -
- //用大括号括起来的列表对容器赋值
- v = { 5, 4, 3, 2, 1 };
- return 0;
- }
④补充
⑤initializer_list使用示例
-
- template<class T>
- class vector
- {
- public:
- typedef T* iterator;
- vector(initializer_list
il) - {
- _start = new T[il.size()];
- _finish = _start;
- _endofstorage = _start + il.size();
-
- //迭代器遍历
- //typename initializer_list
::iterator it = il.begin(); - //while (it != il.end())
- //{
- // push_back(*it);
- // it++;
- //}
-
- //范围for遍历
- for (auto e : il)
- {
- push_back(e);
- }
- }
-
- vector
& operator=(initializer_list il) - {
- vector
tmp(il); - std::swap(_start, tmp._start);
- std::swap(_finish, tmp._finish);
- std::swap(_endofstorage, tmp._endofstorage);
- return *this;
- }
-
- private:
- iterator _start;
- iterator _finish;
- iterator _endofstorage;
- };
⑥如果没有增加以initializer_list作为参数的赋值运算符重载函数,下面的代码也可以正常执行
- vector<int> v = { 1, 2, 3, 4, 5 };
- v = { 5, 4, 3, 2, 1 };
- int main()
- {
- int i = 10;
- auto p = &i;
- auto pf = strcpy;
-
- cout << typeid(p).name() << endl; //int *
- cout << typeid(pf).name() << endl; //char * (__cdecl*)(char *,char const *)
-
- map
dict = { { "sort", "排序" }, { "insert", "插入" } }; - //map
::iterator it = dict.begin(); - auto it = dict.begin(); //简化代码
-
- return 0;
- }
- int main()
- {
- char a = 127;
- char b = 127;
- //c如果给成char,会造成数据丢失,如果能够让编译器根据a+b的结果推导c的实际类型,就不会存在问题
- char c = a + b;
- return 0;
- }
①关键字decltype可以将变量的类型声明为表达式指定的类型
typeid(变量名).name()
的方式可以获取一个变量的类型,但无法用获取到的这个类型去定义变量。- template<class T1, class T2>
- void F(T1 t1, T2 t2)
- {
- decltype(t1*t2) ret;
- cout << typeid(ret).name() << endl;
- }
-
- int main()
- {
- const int x = 1;
- double y = 2.2;
-
- decltype(x*y) ret;
- decltype(&x) p;
- cout << typeid(ret).name() << endl; //double
- cout << typeid(p).name() << endl; //int const *
-
- F(1, 'a'); //int
- F(1, 2.2); //double
-
- return 0;
- }
②decltype除了能够推演表达式的类型,还能推演函数返回值的类型
- void* GetMemory(size_t size)
- {
- return malloc(size);
- }
- int main()
- {
- //如果没有带参数,推导函数的类型
- cout << typeid(decltype(GetMemory)).name() << endl;
-
- //如果带参数列表,推导的是函数返回值的类型,注意:此处只是推演,不会执行函数
- cout << typeid(decltype(GetMemory(0))).name() << endl;
- return 0;
- }
③decltype不仅可以指定定义出的变量类型,还可以指定函数的返回类型
- template<class T1, class T2>
- auto Add(T1 t1, T2 t2)->decltype(t1+t2)
- {
- decltype(t1+t2) ret;
- ret = t1 + t2;
- cout << typeid(ret).name() << endl;
- return ret;
- }
-
- int main()
- {
- cout << Add(1, 2) << endl;; //int
- cout << Add(1, 2.2) << endl;; //double
- return 0;
- }
①C++中NULL被定义成字面量0,这样就可能会带来一些问题,因为0既能表示指针常量,又能表示整型常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。
- /* Define NULL pointer value */
- #ifndef NULL
- #ifdef __cplusplus
- #define NULL 0
- #else /* __cplusplus */
- #define NULL ((void *)0)
- #endif /* __cplusplus */
- #endif /* NULL */
②在大部分情况下使用NULL不会存在什么问题,但是在某些极端场景下就可能会导致匹配错误
int*
的重载函数,但最终却因为NULL本质是字面量0,而导致NULL匹配到了参数为int
类型的重载函数,因此在C++中一般推荐使用nullptr。- void f(int arg)
- {
- cout << "void f(int arg)" << endl;
- }
-
- void f(int* arg)
- {
- cout << "void f(int* arg)" << endl;
- }
-
- int main()
- {
- f(NULL); //void f(int arg)
- f(nullptr); //void f(int* arg)
- return 0;
- }
C++11中新增了四个容器,分别是array、forward_list、unordered_map和unordered_set。
- int main()
- {
- array<int, 10> a1; //定义一个可存储10个int类型元素的array容器
- array<double, 5> a2; //定义一个可存储5个double类型元素的array容器
- return 0;
- }
①与普通数组相比:
②但array容器与其他容器不同的是,array容器的对象是创建在栈上的,因此array容器不适合定义太大的数组。
①forward_list很少使用
②一般情况下要用链表我们还是选择使用list容器。
①内置类型转换为string
②string转换成内置类型