C++入门8 构造函数析构函数顺序|拷贝构造

一,构造函数析构函数

调用顺序

我们先来看下面的代码:

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring> 
using namespace std;
class student {
public:
    char my_name[20];
    int my_id;
    student(int a) {
        my_id = a;
        cout << "构造函数被调用" <<" 学生id为: "<<my_id <<endl;
    }
    ~student() {
        cout<< "析构函数被调用" << " 学生id为: " << my_id << endl;
    }
};

int main() {
    student a(10);
    student b(20);
    cout << endl;
    return 0;
}

这个代码简单的定义了一个学生类,初始化了构造函数和析构函数,a,b赋予初始值,那么他们析构构建顺序又是怎样的呢

可以看到,先定义的先调用构造函数,同时后调用析构函数,这是为什么呢

因为我们系统变量都是在栈区去定义的,我们的栈是一个先进后出的结构,所以导致了这样的情况出现。

全局变量出现

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring> 
using namespace std;
class student {
public:
    char my_name[20];
    int my_id;
    student(int a) {
        my_id = a;
        cout << "构造函数被调用" <<" 学生id为: "<<my_id <<endl;
    }
    ~student() {
        cout<< "析构函数被调用" << " 学生id为: " << my_id << endl;
    }
};

student max(100);
int main() {
    student a(10);
    student b(20);
    cout << endl;
    return 0;
}
student min(1);

这个代码的顺序又是如何呢,min变量又会不会参与我们的调用的,我们看看运行结果便知。

可以看到,min参与了调用,因为全局变量在预编译之后,编译之前便会全部初始化,与他的位置无关。

但因为min在主函数后面,所以打印等操作是不被允许的。

还有一件事,如果我们的全局变量和局部变量命名冲突了又该如何呢

我们遵循局部优先的原则,如果想使用全局变量,需要使用 ::全局域解析符

static

static是静态关键字,使用他可以是变量在需要销毁的时候保留,可以作用在for循环,函数返回值等上,看代码:

cpp 复制代码
int main() {
    //student a(10);
    //student b(20);
    cout << endl;
    for (int i = 0; i < 10; i++)
    {
        static student a(10);
        
    }

    return 0;
}

难道就因为我们使用了static关键字,我们每次的循环都需要创建一变a吗。

编译器当然不会这么做,他只会在第一次循环创建,那么他是怎么知道这是第几次创建呢,

我们发现a下面赋值为一,这就是编译器的处理,这个位置叫做标记域,编译器如果发现标记域为一,那就是已经创建过的变量,如果为0,那就是还未创建。

二,拷贝构造

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring> 
using namespace std;

class student {
public:
    char my_name[20];
    int my_id;
    student(int a) {
        my_id = a;
        cout << "构造函数被调用" << " 学生id为: " << my_id << endl;
    }
    student() {
        my_id = 0;
        cout << "构造函数被调用" << " 学生id为: " << my_id << endl;
    }
    ~student() {
        cout << "析构函数被调用" << " 学生id为: " << my_id << endl;
    }
    student(const student& it) :my_id(it.my_id) {
        cout << "拷贝构造函数被调用" << endl;
    }
    void Setvalue(int c) {
        my_id = c;
    }
};

student func(student c) {
    c.Setvalue(10);
    return c;
}

int main() {
    student a(10);
    student b = func(a); // 使用func函数来创建b
    cout << endl;

    return 0;
}

这段代码,我们会输出什么,思考

为什么会有两个拷贝构造函数呢,原因是我们在函数中试图返回一个学生类,我们知道函数返回值存储在eax寄存器中,而这个寄存器大小很小,只有四个字节,我们的学生类远远超过四个字节,所以编译器就需要想办法了,他同样拷贝构造了一个一摸一样的学生类在主函数栈帧空间里,eax存储这个学生类的地址空间,这样就可以正常返回了,也就出现了两个拷贝构造函数调用。

相关推荐
我材不敲代码几秒前
Python实现打包贪吃蛇游戏
开发语言·python·游戏
身如柳絮随风扬1 小时前
Java中的CAS机制详解
java·开发语言
-dzk-2 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
韩立学长2 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
风筝在晴天搁浅2 小时前
hot100 78.子集
java·算法
Jasmine_llq2 小时前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪3 小时前
快速进制转换
笔记·算法
froginwe113 小时前
Scala 循环
开发语言
m0_706653233 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你913 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口