本文主要是介绍C++入门8 构造函数析构函数顺序|拷贝构造,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一,构造函数析构函数
调用顺序
我们先来看下面的代码:
#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赋予初始值,那么他们析构构建顺序又是怎样的呢
可以看到,先定义的先调用构造函数,同时后调用析构函数,这是为什么呢
因为我们系统变量都是在栈区去定义的,我们的栈是一个先进后出的结构,所以导致了这样的情况出现。
全局变量出现
#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循环,函数返回值等上,看代码:
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,那就是还未创建。
二,拷贝构造
#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函数来创建bcout << endl;return 0;
}
这段代码,我们会输出什么,思考
为什么会有两个拷贝构造函数呢,原因是我们在函数中试图返回一个学生类,我们知道函数返回值存储在eax寄存器中,而这个寄存器大小很小,只有四个字节,我们的学生类远远超过四个字节,所以编译器就需要想办法了,他同样拷贝构造了一个一摸一样的学生类在主函数栈帧空间里,eax存储这个学生类的地址空间,这样就可以正常返回了,也就出现了两个拷贝构造函数调用。
这篇关于C++入门8 构造函数析构函数顺序|拷贝构造的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!