如:将类实例通过值传递给函数,在函数退出作用域时会调用析构函数,在调用者退出时会再次析构
错误代码
#include <iostream>
using namespace std;
class custom_class
{
public:
int* i;
short s{0};
custom_class() = default;
~custom_class()
{
cout << "析构 s=" << s << endl;
delete[] i;
}
custom_class(const custom_class &old) //拷贝构造函数
{
i = old.i;
s = old.s + 10;
cout << "call copy constructor" << endl;
}
};
void func(custom_class c)
{
cout << "func, c.i=" << c.i << ", c.s = " << c.s << "\n";
}
int main()
{
custom_class c1;
c1.i = new int[3] {1, 2, 3};
c1.s = 10;
func(c1); //这里在传参时也会调用拷贝构造函数,函数内的形参变量c是浅拷贝的对象
//此时c1也将自动调用析构函数,但是c1.i和func函数形参c.i是相同的指针,c.i已经在func退出作用域时释放了
//c1.i成为了野指针(悬空指针),所以调用析构函数时程序会崩溃
return 0;
}解决方法1
//传引用
void func(custom_class &c)
{
cout << "func, c.i=" << c.i << ", c.s = " << c.s << "\n";
}
func(c1);//传指针
void func(custom_class *c)
{
cout << "func, c.i=" << c->i << ", c.s = " << c->s << "\n";
}
func(&c1);解决方法2
在析构时,将指针设置为nullptr,释放空指针不会有问题
class custom_class
{
public:
int* i;
short s{0};
custom_class() = default;
~custom_class()
{
cout << "析构 s=" << s << endl;
delete[] i;
i = nullptr;
}
custom_class(const custom_class &old) //拷贝构造函数
{
i = old.i;
s = old.s + 10;
cout << "call copy constructor" << endl;
}
};