Effective C++笔记(2)

本文探讨了C++中构造函数、析构函数及赋值操作的重要概念。包括默认函数的行为、自我赋值处理、析构函数的虚拟性、避免异常逃逸等问题,并提供了实用的编程技巧。

Effective C++笔记
第二章 构造/析构/copy赋值 05~12

P5:了解C++默默编写并调用哪些函数

1:编译器可以暗自为class创建 default构造函数、copy构造函数、copy assignment操作符、析构函数。 唯有这些函数被需要调用,他们才会被编译器创建出来。
2:如果你打算在一个“内含引用成员”或者“内含const成员”的class内支持赋值操作,你必须自己定义copy assignment操作符。
3:如果base classes将copy assignment操作符声明为private,编译器将拒绝为子类生成copy assignment操作符。
4:编译器产生的析构函数是个non-virtual函数。

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

1:为驳回编译器自动提供的功能,可以将相应的成员函数声明为private并且不予实现。或者使用Uncopyable这样的base class方法。

class Uncopyable{
    protected:              //允许derived对象构造和析构
        Uncopyable(){}
        ~Uncopyable(){}
    private:                //但是阻止copying
        Uncopyable( const Uncopyable& );
        Uncopyable& operator=(const Uncopyable&);

};

P7:为多态基类声明 virtual 析构函数

1:如果析构函数不是virtual,则当子类对象是经由一个base class指针析构的时候,他的derived部分会没被销毁。
2:多态性质的base class应该声明一个virtual析构函数。如果class带有virtual函数,它就应该有一个virtual析构函数。
3:class设计的目的如果不是作为base class使用,或不是为了具备多态性,就不该声明virtual析构函数。 STL容器vector,list,set,string等都是non-virtual析构。
4:具有多态性的base class的设计目的是为了用来“通过base class接口处理derive对象”。
5:析构函数的运作方式是,最深层派生的那个class其析构函数最先被调用,然后是每个base class的析构函数被调用。
6:抽象类的virtual析构函数应该有一份定义,原因是第5条在子类的析构函数中会调用抽象类的析构函数。

virtual ~AWOW()=0;  //声明抽象析构函数

AWOW::~AWOW()(){}  //抽象析构函数的定义

P8:别让异常逃离析构函数

1:析构函数如果可能抛出异常,应该捕获异常。并且提供一个普通函数给用户机会自己处理该操作。

class DBConn{
    public:
        void close()        //给客户端一个机会处理可能导致异常的行为
        {
            db.close();
            closed = true; 
        }
        ~DBConn()
        {
            if(!closed)
            {
                try{
                    db.close();
                }
                catch(...){
                    //记录下来并结束程序或吞下异常不做处理。
                }
            }
        }
    private:    
        DBConnection db;
        bool closed;
};

P9:绝不在构造和析构过程中调用virtual函数

1:在deviced class对象的base class构造期间,对象的类型还只是base clas对象而不是deviced class对象! virtual函数只会被解析到base class,对象在deviced class的构造函数开始之前不会成为一个deviced class对象。析构函数同样的道理,只是析构顺序自deviced class到base class。
2:可以让deviced class将必要的信息向上传递至base class构造函数去调用non-virtual函数。

P10:令operator= 返回一个 reference to *this

1:令赋值操作符返回一个reference to *this,这样可以实现连锁赋值。如 x=y=z=“str”;

P11:在operator= 中处理自我赋值

1:使用“证同测试”、语句顺序调整、copy-and-swap等方式确保operator=的自我赋值是正确的。
2:确保然后函数如果操作多个对象时,其中有多个对象是同一个对象时,其行为仍然正确。

class Widget{
    void swap(Widget& rhs); //交换*this和rhs的数据,详见P29。
    BitMap* pb;
};

Widget& Widget::operator=(const Widget& rhs)
{
    if(this == &rhs) return *this; //证同测试

    Widget temp(rhs);   //为rhs数据制作一份副本
    swap(temp);         //将*this与副本数据交换;copy-and-swap技术
    return *this;
}
Widget& Widget::operator=(const Widget& rhs)
{
    BitMap* pOrig = pb;
    pb = new BitMap(*rhs.pb);
    delete pOrig;   //这么写的目的是我们需要注意在复制pb前不能删除pb。
    return *this;
}

P12:复制对象时勿忘其每一个成分

1:当编写copying函数时,应确保复制“对象内的所有成员变量”,确保调用所有base class内适当的copying函数复制”所有base class成分”。
2:不要以某个copying函数去实现另一个copying函数,应该把功能放在第三个init函数中去由copying函数调用。

PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
    :Customer(rhs)          //调用base class的copy构造函数
{
    logCall("拷贝构造函数");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
    logCall("复制操作符");
    Customer::operator=(rhs);   //对base class成分进行赋值操作
    priority = rhs.priority;
    retern *this;   
}
基于模拟退火的计算器 在线运行 访问run.bcjh.xyz。 先展示下效果 https://pan.quark.cn/s/cc95c98c3760 参见此仓库。 使用方法(本地安装包) 前往Releases · hjenryin/BCJH-Metropolis下载最新 ,解压后输入游戏内校验码即可使用。 配置厨具 已在2.0.0弃用。 直接使用白菜菊花代码,保留高级厨具,新手池厨具可变。 更改迭代次数 如有需要,可以更改 中39行的数字来设置迭代次数。 本地编译 如果在windows平台,需要使用MSBuild编译,并将 改为ANSI编码。 如有条件,强烈建议这种本地运行(运行可加速、可多次重复)。 在 下运行 ,是游戏中的白菜菊花校验码。 编译、运行: - 在根目录新建 文件夹并 至build - - 使用 (linux)(windows) 运行。 最后在命令行就可以得到输出结果了! (注意顺序)(得到厨师-技法,表示对新手池厨具) 注:linux下不支持多任务选择 云端编译已在2.0.0弃用。 局限性 已知的问题: - 无法得到最优解! 只能得到一个比较好的解,有助于开阔思路。 - 无法选择菜品数量(默认拉满)。 可能有一定门槛。 (这可能有助于防止这辅助工具的滥用导致分数膨胀? )(你问我为什么不用其他语言写? python一个晚上就写好了,结果因为有涉及json读写很多型没法推断,jit用不了,算这个太慢了,所以就用c++写了) 工作原理 采用两层模拟退火来最大化总能量。 第一层为三个厨师,其能量用第二层模拟退火来估计。 也就是说,这套方法理论上也能算厨神(只要能够在非常快的时间内,算出一个厨神面板的得分),但是加上厨神的食材限制工作量有点大……以后再说吧。 (...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值