列表初始化
内置类型的列表初始化
int a{1};
int b = {2};
//容器的列表初始化
vector<int> arr{1, 2, 3, 4, 5};
//动态数组也可以
int* arr3 = new int[5]{1,2,3,4,5};
map<int, int> m{{1,1}, {2,2,},{3,3},{4,4}};
自定义类型也可以列表初始化
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;
}
多个对象想要支持列表初始化,需给该类(模板类)添加一个带有initializer_list类型参数的构造函数即可。
注意:initializer_list是系统自定义的类模板,该类模板中主要有三个方法:begin()、end()迭代器以及获取区间中元素个数的方法size()
#include <initializer_list>
template<class T>
class Vector {
public:
// ...
Vector(initializer_list<T> l): _capacity(l.size()), _size(0)
{
_array = new T[_capacity];
for(auto e : l)
_array[_size++] = e;
}
Vector<T>& operator=(initializer_list<T> l) {
delete[] _array;
size_t i = 0;
for (auto e : l)
_array[i++] = e;
return *this;
}
private:
T* _array;
size_t _capacity;
size_t _size;
};
类型推导
auto:编译时根据初始化表达式进行类型推导。
decltype :运行时类型识别。
decltype是根据表达式的实际类型推演出定义变量时所用的类型
推演表达式类型作为变量的定义类型
decltype(1 + 2) a;推演函数返回值的类型
decltype(func(10)) b;
//decltype: 如果有参数列表,推导返回值类型
cout << "b: type: "<< typeid(b).name() << endl;
//decltype: 如果没有参数列表,只有函数名,推导为函数的接口类型
cout << typeid(decltype(func)).name() << endl;
final关键字
class B final //表示这个类禁止被继承
{};
override 关键字
保证这个函数要在子类中被重写,没重写就报错
默认成员函数控制
显式缺省函数
在C++11中,可以在默认函数定义或者声明时加上=default,从而显式的指示编译器 生成该函数的默认版本,用=default修饰的函数称为显式缺省函数
删除默认函数
当我们不想让某个成员函数生效时,可以使用delete
class A
{
public:
A(int a): _a(a)
{}
// 显式缺省构造函数,由编译器生成
A() = default;
// 在类中声明,在类外定义时让编译器生成默认赋值运算符重载
A& operator=(const A& a);
//禁止编译器生成默认的拷贝构造函数以及赋值运算符重载
A(const A&) = delete;
A& operator(const A&) = delete;
private:
int _a;
};
A& A::operator=(const A& a) = default;
右值引用
左值:既可以出现在=的两边、或者可以取地址的.
不是右值的都为左值.
右值:只能出现在=的右边,或者不可以取地址.右值包含以下
纯右值: 常量, 临时变量/匿名变量
临时变量/匿名变量:函数以值返回的变量, 调用类的构造函数创建的变量
将亡值: 声明周期即将结束
引用:
左,右值引用—语法意义:都是变量的别名。
左值引用:既可以引用左值, 也可以引用右值。
如果左值引用引用了右值:需要加const。
右值引用:只能引用右值。
右值引用最大作用:
表示指向的实体为右值,实体的资源可以被直接拿走, 提高拷贝的效率,本质为浅拷贝。
移动构造:
参数类型为右值引用, 提高拷贝的效率
1.相对于拷贝构造,可以在实现浅拷贝的情况下,不产生错误。
2.右值引用指向的实体一般是生命周期马上要结束的实体(将亡值),可以直接
获取右值弓|用所指向的实体资源,不需要深拷贝。
移动赋值:
参数类型为右值引用
也是浅拷贝,原理同上