目录
六、新增加容器---静态数组array、forward_list以及unordered系列
9.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.标准库支持单个对象的列表初始化
class A
{
public:
A(int a = 10)
:_a(a)
{}
A(int a, char c)
:_a(a)
, _c(c)
{}
private:
int _a;
char _c;
};
void test2()
{
A a;
A a0 = 10;//单参构造函数隐式类型转换: 10会先调用默认构造函数成为一个匿名对象,再使用拷贝构造进行拷贝赋值
//A a2 = 10,'a';//报错,不支持
//C++11: 自定义类型支持列表初始化
A a1 = { 1, 'c' };
}
2. 多个对象的列表初始化
template<class T>
//自定义容器类如果要支持列表初始化,需要实现initializer_list接口
class Vector
{
public:
Vector(const initializer_list<T>& lst)//实现initializer_list接口
:_array(new T[lst.size()])
{
int idx = 0;
for (const auto& e : lst)
{
_array[idx++] = e;
}
}
private:
T* _array;
};
void test4()
{
//自定义容器类无法天然支持列表初始化
//Vector<int>vec0 = { 1, 2, 3, 30 };
//实现initializer_list接口就可以
Vector<int>vec = { 1, 2, 3, 30 };
}
二、变量类型推导
2.1为什么需要类型推导
在定义变量时,必须先给出变量的实际类型,编译器才允许定义,但有些情况下可能不知道需要实际类型怎么给,或者类型写起来特别复杂。例如:
#include <map>
#include <string>
int main()
{
short a = 32670;
short b = 32670;
// c如果给成short,会造成数据丢失,如果能够让编译器根据a+b的结果推导c的实际类型,就不会存在问
题
short c = a + b;
std::map<std::string, std::string> m{ { "apple", "苹果" }, { "banana", "香蕉" } };
// 使用迭代器遍历容器, 迭代器类型太繁琐
std::map<std::string, std::string>::iterator it = m.begin();
while (it != m.end())
{
cout << it->first << " " << it->second << endl;
++it;
}
return 0;
}
C++11中,可以使用auto来根据变量初始化表达式类型推导变量的实际类型,可以给程序的书写提供许多方便。将程序中c与it的类型换成auto,程序可以通过编译,而且更加简洁。例如:
#include <map>
#include <string>
int main()
{
short a = 32670;
short b = 32670;
auto c = a + b;//类型自动推导
std::map<std::string, std::string> m{ { "apple", "苹果" }, { "banana", "香蕉" } };
for (auto& it : m)
{
cout << it.first << " " << it.second << endl;
}
system("pause");
return 0;
}
2.2 decltype类型推导
2.2.1为什么需要decltype
auto使用的前提是:必须要对auto声明的类型进行初始化,否则编译器无法推导出auto的实际类型。但有时候可能需要根据表达式运行完成之后结果的类型进行推导,因为编译期间,代码不会运行,此时auto也就无能为力。
template<class T1, class T2>
T1 Add(const T1& left, const T2& right)
{
return left + right;
}
2.2.2 decltype测试(包含推演表达式类型作为变量的定义类型,推演函数返回值的类型)
int add(int x,int y){
return x+y;
}
int main(){
double i=0;
decltype(i) a; // double
decltype(add()) b; //int 注意括号。不带括号就是函数指针了。
}
int fun1(int a)
{
return a;
}
void test5()
{
auto a = 10; //编译时类型推导
decltype(a + 10) c;//c的类型是在运行时类型推导:通过表达式结果确定的,是RTTI思想
decltype(test4) d;//推导test4函数类型
decltype(fun1) e;
decltype(fun1(a)) f;
cout << typeid(e).name() << endl;//int _cdecl<int>-->函数类型
cout << typeid(f).name() << endl;//int-->int类型
}
三、基于范围for的循环
参考:https://mp.csdn.net/console/editor/html/102709550
四、final与override
类 + fina: 不能被继承的类
虚函数+fina: 不能被重写的函数 override: 强制重写父类的虚函数override用法:强制重写父类的方法,强制实现多态,体现了接口继承
参考:https://mp.csdn.net/console/editor/html/104690689
五、智能指针
参考:https://mp.csdn.net/console/editor/html/105661575
六、新增加容器---静态数组array、forward_list以及unordered系列
array:静态数组。在栈上开辟的固定大小数组
forward_list : 不带头单向非循环链表
参考:https://mp.csdn.net/console/editor/html/106152063
七、委派构造函数
委派构造函数也是C++11中对C++的构造函数的一项改进,其目的也是为了减少程序员书写构造函数的时间。通过委派其他构造函数,多构造函数的类编写更加容易。
class Info {
public:
Info() : _type(0), _name('a')
{
InitRSet();
}
Info(int type) : _type(type), _name('a')
{
InitRSet();
}
Info(char a)