【Effective C++ 条款05-07 笔记】【C++默默编写并调用哪些函数】【禁止编译器自动生成函数】【什么时候基类要带虚析构函数】

本文详细探讨了如何防止C++类的拷贝操作,通过私有化构造与赋值函数以及unCopyable基类来限制复制。此外,强调了虚析构函数在多态清理内存的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

条款05:了解C++默默编写并调用哪些函数

一个空类,编译器会自动声明:

  • 默认构造函数(对于非空类:只在没有自定义任何构造函数的时候,才会由编译器补充)
  • 拷贝构造函数
  • 拷贝赋值运算符
  • 析构函数(非虚函数)

注意:当一个class内含有reference/const成员时,编译器不提供拷贝赋值运算符的补充,只能由程序员自己编写

这是因为C++不允许改变reference成员的指向,也不允许更改const成员

条款06:若不想使用编译器自动生成的函数,就该明确拒绝

  • 问题:

比如说想要禁止一个类对象的拷贝操作,就要禁止拷贝构造函数和拷贝赋值运算符。但是不声明这两个函数,编译器可能会自动生成;要想避免编译器自动生成,又要自己声明一份;怎样都避免不了产生这两个函数。

  • 解决方案1:

将拷贝构造函数、拷贝赋值运算符声明为private函数,这样在类外部不能以拷贝构造和复制的形式公然调用这两个函数

class A {
public:
    A() = default;
private:
    A(const A&);
    A& operator=(const A&);
};
  • 解决方案1存在的问题:

以class A为例,A的其他成员函数和友元函数还是能调用class A的private函数。由此引出解决方案2

  • 解决方案2:

定义一个基类专门阻止拷贝动作

class unCopyable {
protected:
    unCopyable() {}
    ~unCopyable() {};
private:
    unCopyable(const unCopyable&) {}
    unCopyable& operator=(const unCopyable&) {}
};

class A : private unCopyable{
public:
    A() = default;
};

此时,就算是class A的成员函数和友元函数,在尝试拷贝A的对象时,编译器会“试着“生成拷贝构造函数和拷贝赋值运算符,但是这种”试着“会被基类阻止,因为基类的对应函数时private,子类不能调用

条款07:为多态基类声明virtual析构函数

当一个基类指针指向一个子类对象时,若基类的析构函数不是virtual函数,那么在delete基类指针的时候,只会释放基类对象的资源,不会释放子类对象的资源,从而造成内存泄漏

任何带有virtual函数的class都应该有一个virtual析构函数

虚函数的实现原理

  • 每个含有virtual函数的class都有一个vtbl(虚函数表),vtbl中存储的是指向各个虚函数的函数指针;

  • 每个对象内存空间内存在一个vptr(虚指针),这个vptr指向类的vtbl

  • 当对象调用某个virtual函数的时候,编译器根据对象的vptr找到类的vtbl,在vtbl中寻找适当的函数指针

注意:不作为基类使用的class不要声明析构函数为virtual函数,因为虚表和虚表指针会占用额外的内存;同时,std::string和STL容器的析构函数都是non-virtual,不要作为基类使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值