C++简记--被两次调用的析构

析构遇上拷贝—“被两次调用的析构”

类的构造函数(包括初始化列表)的使用稀松平常

但当析构函数遇上拷贝初始化,就有可能出现一些有意思的事情

涉及:赋值符重载函数参数应当是引用类型,否则可能导致意外的构造

到上面第三句已经是这篇文章的全部内容了,若需要实例说明,如下:

意外的析构(析构函数调用次数多于生命的对象数)
且看代码:

//我们假设有一个类:
class catcher{
public:
    catcher(const string& s):
    name(s)//初始化列表
    {
        cout<<"catcher()"<<endl;
    }
    catcher(const catcher& z)//拷贝
    {
        cout << "catcher(const catcher&)" << endl;
        name = z.name;
    }
	/*赋值运算符重载---关键所在*/
    catcher& operator=(const catcher k){
        cout << "catcher& operator=(const catcher k)" << endl;
        name = k.name;
        return *this;
    }
    ~catcher() {	//析构
        cout << "~catcher()" << name << endl;
    }
    

    void chName(const string& s) {name = s;}
private:
    string name="init value";

};

为了显示各个成员函数的调用情况,我们在进入每个函数后都输出函数原型到控制台
详细的我们在这个类使用后,再细说

//使用用这个类
int main()
{
	//初始化两个对象Markson和Hancici
   catcher Markson("Markson");
   catcher Hancici("Hancici");
   Hancici = Markson;//使用重载的运算符将Markson的name拷贝给Hancici
   return 0;
}

输出结果:

catcher()
catcher()
catcher(const catcher&)
catcher& operator=(const catcher k)
~catcher()Markson
~catcher()Markson
~catcher()Markson

从输出文本的首尾可以看到,只调用了两次构造函数,但程序结束时却调用了3次析构函数。两个对象,三次析构,明显是不合理的。推测,存在除markson和Hancici之外的第三个被构造的对象

观察输出结果中间部分发现,本来main()只调用了赋值运算符的重载函数,但结果却多了一次对拷贝拷贝函数的调用,这儿也许是问题所在。

再看赋值符重载函数的参数——非引用类型。这意味着在传参时会对参数对象做一次拷贝,此时参数对象是一个catcher对象,自然地会调用拷贝构造函数
catcher(const catcher&)构造一个新的对象,也即是原型catcher& operator=(const catcher k)
中的参数k。所以z就是那个“除Markson和Hancici之外第三个被构造的对象”

我们把赋值符重载函数作如下修改:

catcher& operator=(const catcher k) ----> catcher& operator=(const catcher& k)
//记得同时修改输出语句中的函数原型文本

再编译运行得到如下输出:

catcher()
catcher()
catcher& operator=(const catcher& k)    
~catcher()Markson
~catcher()Markson

“意外的析构”消失了,ok。

赋值符重载函数参数应当是引用类型,否则可能导致意外的构造
涉及:函数的引用类型和非引用类型参数

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值