C++拷贝构造函数调用时机及陷阱

拷贝构造调用有四种

  1. 用一个对象 初始化 另一个对象时
  2. 函数实参传递给形参时,这也差不多是初始化啦
  3. 函数返回值,C++编译器在这做的就很奇怪了,今天早上调了一早上
#define _CRT_SECURE_NO_WARNINGS

#include 

using namespace std;

//大家可以看一下陷阱在哪
class Teacher
{
public:
    Teacher(char *name, int age)
    {
        this->name_len = strlen(name);
        this->name = new char[name_len + 1];
        strcpy(this->name, name);
        this->age = age;
    }
    Teacher(const Teacher &obj)
    {
        cout << "调用了copy构造函数... " << endl;
        if (obj.name_len < 0)
        {
            return;
        }
        if (name != NULL) //
        {
            delete[] name;
            name = NULL;
        }
        name_len = obj.name_len;
        name = new char[name_len + 1];
        strcpy(name, obj.name);
        age = obj.age;
    }
public:
    char* name; //姓名
    int name_len; //姓名的长度
    int age; //年龄
};
  • 看着好像是问题不大,我们来运行一下
void main()
{
    Teacher t1("calf", 50);
    cout << t1.age << t1.name << endl;

    Teacher t2("aaaa", 15);
    cout << t2.age << t2.name << endl;

    Teacher t3 = t1;
    cout << t3.age << t3.name << endl;
}

C++拷贝构造函数调用时机及陷阱_第1张图片
ok,运行成功
- 然后我们开始测试函数返回值调用的copy构造函数

//先写个函数
Teacher getT()
{
    Teacher tmp("young", 12);
    return tmp;
}
//调用试试
void main()
{
    Teacher t1("calf", 50);
    cout << t1.age << t1.name << endl;

    Teacher t2("aaaa", 15);
    cout << t2.age << t2.name << endl;

    Teacher t3 = t1; //加了这四行
    cout << t3.age << t3.name << endl;  
    t3 = getT(); 
    cout << t3.age << t3.name << endl;
}

C++拷贝构造函数调用时机及陷阱_第2张图片
执行到这就宕机了,,,
C++拷贝构造函数调用时机及陷阱_第3张图片
通过调试,发现拷贝构造函数里去掉这几行就行了

Teacher(const Teacher &obj)
    {
        cout << "调用了copy构造函数... " << endl;
        if (obj.name_len < 0)
        {
            return;
        }
        /*这几行
        if (name != NULL) //
        {
            delete[] name;
            name = NULL;
        }
        */
        name_len = obj.name_len;
        name = new char[name_len + 1];
        strcpy(name, obj.name);
        age = obj.age;
    }

查了些资料,原因如下:
在执行这句的时候 t3 = getT(); , 会产生一个匿名对象(就是没有任何调用的对象),会先把getT()函数的tmp对象通过copy构造函数,初始化这个匿名对象,然后析构这个tmp对象完成退出这个函数,然后通过等号操作符(可以重载)把产生的匿名对象赋给t3,再析构这个匿名对象。
C++拷贝构造函数调用时机及陷阱_第4张图片

  • 现在开始说我们的陷阱了,个人觉得宕机的原因: C++除了全局变量以外的变量都不会自动赋初值,即我们Teacher类的char *name的初始值是随机的,匿名对象的name值不为空,故析构了还没分配内存的name野指针。

ps:C++博大精深,觉得这个解析可能也不是很合理,望指点。

你可能感兴趣的:(C++)