美文网首页
NDK-021: C++02: 构造函数、析构函数和拷贝构造函

NDK-021: C++02: 构造函数、析构函数和拷贝构造函

作者: xqiiitan | 来源:发表于2025-01-07 09:39 被阅读0次

21:C++02:C++基础 - 构造函数、析构函数和拷贝构造函数

1.构造函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

class Student
{
public:
    // 1.构造函数
    Student(){// 空参数构造函数
        cout << "空参数构造函数"<< endl;
    }
    // Student(char* name): age(0) { // 一个参数构造函数, 相当于 this->age = 0, age默认值为0
    //  cout << "一个参数构造函数" << endl;
    //  this->name = name;
    //  // this->age = 0;
    // }
    // Student(char* name): age(0), sex('男'){ // 多个参数有默认值. char sex;
    // }

    // 2.构造函数相互调用
    Student(char* name) :Student(name,0){// 一个参数的构造函数,调用两个参数的构造函数,注意:先会调用两个参数的构造函数,然后才会执行当前构造函数
        cout << "一个参数构造函数" << endl;
    }
    Student(char* name, int age){// 两个参数构造函数
        cout << "两个参数构造函数" << endl;
        this->name = (char*)malloc(sizeof(char)*100); // 给name开辟100个字节
        strcpy(this->name, name);
        // this->name = name;
        this->age = age;
    }

    // 3. 析构函数, 如果有在对象内部开辟堆内存,可以在析构函数中释放内存
    ~Student(){
        cout << "析构函数" << endl;
        // 临终遗言,对象被回收的时候会被调用
        // 释放内存
        free(this->name);
        this->name = NULL;
    }

    // 4.拷贝构造函数,对象会有一个默认的拷贝构造函数,用来对象之间的赋值
    Student(const Student& stu){// 常量的引用
        cout << "拷贝构造函数" << endl;
        // this->name = stu.name;// 浅拷贝
        // 如果动态开辟内存,一定要采用深拷贝
        this->name = (char*)malloc(sizeof(char)* 100);
        strcpy(this->name, stu.name); // 名字拷贝到开辟的内存中
        this->age = stu.age;
    }

// 属性声明
private:
    int age;
    char* name;
public:
    int getAge(){
        return this->age;
    }
    char* getName(){
        return this->name;
    }
    void setAge(int age){
        this->age = age;
    }
    void setName(char* name){
        this->name = name;
    }
};

void main(){
    // Student stu;// 1. 默认调用空参的构造函数
    // stu.setAge(24);
    // stu.setName("Darren");
    // Student stu("Darren",24); // 2. 调用两个参数的构造函数
    // cout << stu.getName() << " , " << stu.getAge() << endl; // 使用·访问    

    // 3. 用 new 关键字,返回的是一个 Student 的一级指针地址,要使用箭头访问
    // Student *stu = new Student("Darren",24);
    // 4. 用 malloc 的方式,并没有调用空参的构造函数。也没调用别的构造函数。
    // Student *stu = (Student*)malloc(sizeof(Student));
    // stu->setAge(24);
    // stu->setName("Darren");

    // 构造函数相互调用: 两个参数构造函数--> 一个参数构造函数
    Student *stu = new Student("Darren");
    cout << stu -> getName() << " , " << stu->getAge() << endl;
    delete(stu); // new的对象,使用delete释放。 【free对象,不会调用析构函数】
    getchar();
}

2.析构函数:以‘~’波浪线符号开头。

析构函数只能有一个,且不能有任何输入参数。构造函数可以有N个。
如果有在对象内部开辟堆内存,可以在析构函数中释放内存
相当于对象的临终遗言,对象回收的时候会被调用,一般在这里释放内存。做对象的善后处理。
Java对象的,被回收会调用finalize()方法。

    // 3. 析构函数, 如果有在对象的内部开辟 堆内存,可以在析构函数中释放内存
    ~Student(){
        cout << "析构函数" << endl;
        // 临终遗言,对象被回收的时候会被调用
        // 释放内存
        free(this->name);
        this->name = NULL;
    }

Java 面试题:finalize,finally,final 之间的区别。
finalize:垃圾回收机制,回收该对象时会调用的对象。相当于析构函数。
回收之前会调用这个方法,然后把你所有的回收对象加入到一个Queue中,然后一个个去回收,
可以在这个方法里面,拉活一个对象。
finally:
final:

3. malloc,free,new,delete 的区别。

malloc,new。都是开辟内存和使用
都是开辟和释放内存有关。C++ 里面新增了new 和 delete关键字。
malloc/free 他们是一套,不会去调用构造函数和析构函数;
new/delete 它们是一套,会调用构造函数和析构函数。new的对象,一定要delete释放内存(free无效)。
要成对使用malloc/free, 或 new/delete.

void main(){
    // Student stu;// 栈中开辟内存

    // malloc、free、 new、delete 都是开辟和释放内存有关。
    // 1. malloc/free 他们是一套, new/delete 它们也是配套
    // 2. malloc/free 不会去调用构造函数和析构函数
    // Student *stu = (Student*)malloc(sizeof(Student));
    // free(stu);
    // 3. new/delete 会调用构造函数和析构函数,它们是一套。
    // Student *stu = new Student(); // 调用构造函数
    // delete(stu);                  // 调用析构函数
    // 4. 如果用了 new ,那么一定要记得 delete(释放内存)

    getchar();
}

4.拷贝构造函数 符号‘=’

    // 4.拷贝构造函数,对象会有一个默认的拷贝构造函数,用来对象之间的赋值
    Student(const Student& stu){ // 常量的引用: 一块内存的别名
        cout << "拷贝构造函数" << endl;
        // this->name = stu.name;// 浅拷贝。让新的指针指向它。

        // **** 【深拷贝】:如果动态开辟内存,一定要采用深拷贝,否则会出现问题(多次析构 释放name会报错)
        this->name = (char*)malloc(sizeof(char)* 100);
        strcpy(this->name, stu.name); // 名字拷贝到开辟的内存中
        this->age = stu.age;
    }
struct Person {
    int age;
    char* name;
};
void main(){
    Person person1 = {24,"Darren"};
    Person person2 = person1; // = 是赋值,把里面所有定义的属性赋值了一遍,c/c++ 编译器帮我们做的

    cout << &person1 << " , " << &person2 << endl; // 两个地址不一样,两个不同的结构体对象。
    cout << person2.name << " , " << person2.age << endl; // 但是person2,有person1的所有值。
    getchar();
}
void main(){
    Student *stu1 = new Student("Darren",24);
    Student *stu2 = stu1;  // 指针复制然后赋值,没有涉及拷贝构造。
    stu2->setAge(26);
    cout << stu1->getName() << " , " << stu1->getAge() << endl;
    getchar();
}


Student getStudent(char* name){
    Student stu(name);// 栈 ,方法执行完,这个对象就会被回收,但是发现调用了拷贝构造函数,析构函数
    cout << &stu << endl; // 打印对象地址
    return stu;// 会返回一个新的 Student 对象,而栈内开辟中的 stu 是会被回收的.
}
void printStudent(Student stu){// stu 是该方法栈中一个新的对象,拷贝构造函数赋值,方法执行完会调用析构函数
    cout << stu.getName() << " , " << stu.getAge() << endl; // 执行完,会调用析构函数,释放栈中的内存。
}
void main3(){
    // 1. 第一种场景:= 会调用拷贝构造函数
    // Student stu1("Darren", 24); // 新建对象stu1
        // 对象拷贝函数,用来对象之间的赋值。并没有走对象拷贝函数
    // Student stu2 = stu1; // = 是赋值,把里面所有定义的属性赋值,c/c++ 编译器帮我们做的,其实会调用对象的拷贝构造
    // 上面调用:两个参数的构造函数,拷贝构造函数    

    // Student stu2;// 声明变量,同时开辟变量栈内存
    // stu2 = stu1; // 注意:这个不会去调用拷贝构造函数,但是会赋值 与c 的类似

    // 2. 第二种场景:作为参数返回的时候会调用拷贝构造函数
    // Student stu = getStudent("Jack");
    // cout << &stu << endl;   // 打印对象地址,与getStudent()里面的对象地址不是同一个。不是同一个对象。

    // 3. 第三种场景:作为参数传递的时候会调用拷贝构造函数,将对象拷贝一遍。
    // Student stu("Darren", 24); // 两个参数构造函数-->拷贝构造函数赋值。
    // printStudent(stu);

    // 知识的补充:name属性 二次析构的释放,就会有问题。所以 需要使用深拷贝。
    Student stu = getStudent("Jack");
    // cout << stu.getName() << " , " << stu.getAge() << endl;
    printStudent(stu);
    getchar();
}

有点奋斗目标,有点理想。

相关文章

网友评论

      本文标题:NDK-021: C++02: 构造函数、析构函数和拷贝构造函

      本文链接:https://www.haomeiwen.com/subject/iqakyjtx.html