C++默认生成的成员函数

C++默认生成的成员函数

  1. 默认构造函数(如果未显式声明构造函数)
  2. 默认复制构造函数(如果未显式声明复制构造函数)
  3. 析构函数(如果未显式声明析构函数)
  4. =赋值运算符函数(如果未显式声明)
  5. &取地址运算符函数(如果未声明)

首先明确一点,分配对象空间后,一定会调用构造
对象空间释放前,一定会调用构造 至于为什么析构在释放之前调用,是因为如果对象如果先释放,那么就没有对象了,而析构函数又是成员函数,所以,先调用析构,后释放空间。例如,我们可以在析构函数中使用任意一个成员变量,所以,在使用的时候,对象空间一定存在

1.默认构造函数

默认构造函数函数体

class_name(){}

没错,默认构造函数啥也没干,它的作用就是在分配对象空间时,有构造函数可以调用。

什么时候调用

默认无参的构造函数

2.默认复制构造函数——逐成员调用默认复制构造

默认复制构造函数体

class_name(const class_name &obj){
    ...//逐条复制成员变量的值
}

在成员中有指针变量时,这里只是简单的复制了值这可能会引起错误

什么时候调用

  1. 定义时初始化直接用同类对象赋值
  2. 函数值传递时,形参变量初始化
  3. 函数按值返回时,返回值的临时对象空间

3.默认析构函数

默认析构函数体

~class_name(){}

默认的析构函数也是啥也不干,为了在释放对象空间前,有析构函数可以调用。

如果有指针成员,一般在析构函数中释放,不过为了不出错,还需要显式地声明定义复制构造函数和复制运算符函数,否则会发生错误,这里如果不明确,先不要管,在后面会谈到

4.默认的赋值运算符函数——逐成员调用赋值运算符函数

默认赋值运算符函数体

const &operator=(const class_name &obj){
    ...//逐条复制成员变量的值
}

这里也是简单的复制了值,如果成员有指针,也可能引起错误。

什么时候调用

同类对象之间赋值(非定义时初始化)

5.默认的取地址运算符函数——默认返回this,一般不会显式地修改这个函数

6.容易发生的错误

#include <iostream>
using namespace std;
class A {
private:
    int *pint;
public:
    A();
    ~A();
};

A::A() {
    pint = new int(3);
    cout << this << "调用A()" << endl;
}

A::~A() {
    delete pint;
    cout << this << "调用~A() " << endl;
}

int main() {

    A obj1;
    A obj2 = obj1;

    return 0;
}

运行之后发现,有错误。结果显式“只调用了一次构造”(其实调用两次),而且程序会不正常运行。

分析:

明明创建了两个对象,为什么仅输出了一次调用构造函数地信息? 调用了两次,obj2调用了默认的复制构造函数

上面说过,调用默认的复制构造,仅仅复制了值,所以obj1.pint和obj2.pint指向了同一个整型单元,main()结束之后,要释放单元,所以obj2要调用析构函数,将成员指向的单元释放;然后,obj1调用析构函数,再次释放了同一块空间。同一块空间释放两次,这就是程序不正常运行的原因

同样:

A obj3;
obj3 = obj2;

默认的赋值也会造成上述情况

解决方法:重定义复制构造与赋值运算符

class A {
private:
    int *pint;
public:
    A();
    A(const A &obj);
    const A & operator = (const A &obj);
    ~A();
};

A::A() {
    pint = new int(3);
    cout << this << "调用A()" << endl;
}
A::~A() {
    delete pint;
    cout << this << "调用~A() " << endl;
}

重定义复制构造:

A::A(const A &obj) {
    pint = new int(*(obj.pint));
    cout << this << "调用A(const A &)" << endl;
}

重定义复制运算符:

const A &A::operator = (const A &obj) {
    pint = new int(*(obj.pint));
    cout << this << "调用operator=(const A &)" << endl;
    return obj;
}

int main() {

    A obj1;
    A obj2 = obj1;
    A obj3;
    obj3 = obj2;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值