文章目录
- 1.移动构造
- 2.移动赋值
- 对于移动构造/移动赋值的想法
- 3.类成员定义时初始化
- 4.强制生成默认函数的关键字default
- 5.禁止生成默认函数的关键字delete
- 5.1介绍
- 5.2应用场景
- 1.法一:析构函数私有化
- 2.法二: delete关键字
- 思考
- 6.final关键字
- 7.override关键字
1.移动构造
编译器自动生成移动构造
编译器没有自动生成移动构造
2.移动赋值
规则同上
对于移动构造/移动赋值的想法
首先我们思考一下 一个什么样的类需要有移动构造?
回答:一个涉及到深层拷贝的类 因为移动构造的本意就是当遇到右值拷贝时直接交换不再进行深层拷贝
接着我们看为什么大佬这么设计移动构造自动生成的条件
相比之前的默认成员函数 编译器自动生成的移动构造/移动赋值 条件更为苛刻 其实 C++大佬这样设计是完全有道理的 当一个类不需要析构\拷贝构造\赋值重载时
一个不需要析构/拷贝构造\赋值重载的类[一个不需要自己实现析构函数的类 基本上也不需要自己实现拷贝构造和赋值重载] 我们大概可以想象他的成员是这样的:一个内置类型一个自定义类型
对于这样一个类 当我们没有自己实现移动构造 此时编译器会自动生成移动构造 自动生成的这个移动构造完全可以处理这个类的成员 [对于内置类型进行浅拷贝 对于自定义类型 有移动构造调用移动构造 没有调用拷贝构造]
内置类型本来浅拷贝就行 自定义类型如果自己实现移动构造[当前类需要自己实现 那就自己实现一个] 那就调用移动构造 如果没有自己实现 说明当前类不需要移动构造或满足条件自动生成的就够用
3.类成员定义时初始化
C++11允许在类定义时给成员变量缺省值,默认生成的构造函数会使用这些缺省值初始化
4.强制生成默认函数的关键字default
C++11让我们能更好的控制要使用的默认函数。假设我们要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。比如:
- 自己实现了拷贝构造 就不会自动生成 默认拷贝构造/无参构造/移动构造了,那么我们可以使用default关键字显示指定他们生成。
- 自己实现了有参构造 就不会自动生成默认无参构造 那么我们可以使用default关键字显示指定他生成
class Person
{
public:
Person(const char* name = "", int age = 0)
:_name(name)
, _age(age)
{}
//自己实现了拷贝构造 不会再自动生成移动构造
Person(const Person& p)
:_name(p._name)
,_age(p._age)
{}
//强制移动构造生成
Person(Person&& p) = default;
private:
bit::string _name;
int _age;
};
int main()
{
Person s1;
Person s2 = s1;
Person s3 = std::move(s1);
return 0;
}
5.禁止生成默认函数的关键字delete
5.1介绍
如果我们自己与一个类 但是我们不想让别人调用我们这个类的拷贝构造 在C++98中我们可以将这个类的拷贝构造函数 访问属性设置为private 使得他人无法调用 在C++11中我们可以在该函数声明加上=delete,该语法指示编译器不生成对应函数的默认版本,称 =delete修饰的函数 为删除函数。
5.2应用场景
实现一个类 使得这个类只能在堆上创建对象[一个类创建的对象销毁时自动调用析构函数 如果这个对象的析构函数只能在堆区调用 那么我们的目的就达到]
1.法一:析构函数私有化
2.法二: delete关键字
思考
为什么new的对象可以存在?
因为pre是个指针 是个内置类型 只有自定义类型的对象在销毁时才会自动调用析构 而内置类型不会 即析构函数能否调用 对内置类型无影响
但是此时又引发一个问题 析构函数无法被调用 如果此类有这样的成员属性
char* _str;
那么这个类就有资源需要手动释放[本来应该自己实现一个析构函数] 怎么办?
废话不多说 直接上代码 一看便知
class HeapOnly
{
public:
HeapOnly()
{
_str = new char[10];
}
~HeapOnly() = delete;
void Destroy()
{
delete[] _str;
operator delete(this);
//free(this);
}
private:
char* _str;
};
int main()
{
//堆上创建对象
HeapOnly* ptr = new HeapOnly;
//栈上创建对象
HeapOnly hp1;
//数据段上[静态区]创建对象
static HeapOnly hp2;
ptr->Destroy();
//operator delete(ptr);
//free(this);
return 0;
}
6.final关键字
final:修饰父类虚函数,表示该虚函数不能再被重写
7.override关键字
override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错