函数
[TOC]
函数
构造函数
通过类里函数可以给私有成员赋值,同时也可以通过函数return 出值
特殊的成员函数,主要用于创建对象时初始化对象->给对象成员赋予初值
构造函数的特点
- 构造函数的函数名与类名相同
- 构造函数没有返回值类型,也没有返回值
- 构造函数可以重载
没有写构造函数,自己会生成,由于内联函数,牺牲时间换效率
系统给的构造函数
1
Myclass(){}
系统给的构造函数相当于低保
构造函数,在创建时系统就会调用,不能通过对象调用构造函数
默认给的构造函数,是
public
类型const
:改变性质,将变量变成常量对
const
修饰的变量在函数创建时进行赋值:是在初始化的时候赋初值,不是在声明的时候
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include<iostram>
using namespace std;
class chg
{
public:
const int num1;
const int num2;
const int num3;
chg();
private:
};
chg::chg(int n,int i):num1(n),num2(i),num3(3)//括号里面可以是变量也可以是常量
{
}
int main()
{
return 0;
}
析构函数
- 一种特殊的函数,作用是在对象的生命周期结束时进行清理,系统可以自动调用析构函数
- 函数名与类名一致,在前面加上
~
- 没有返回值,也没有参数,但必须有参数表也就是()
- 有低保,没写的话,系统自动分配
- 可以通过外部访问到析构函数
- 在类创建时,自动使用一次,构造,和析构(在生命周期结束时,会自动调用析构函数)
- 先构造的后析构
拷贝构造, 函数
先是构造函数,才可能是拷贝构造函数
有低保,系统会统一给
第一个参数是,该类的对象
操作实例:
1
2
3
4
5
6class Myclass()
{
Myclass();//构造函数
~Myclass();//析构函数
Myclass(Myclass& obj);//拷贝构造函数
}调用时机
使用一个对象给另一个对象进行初始化
使用一个对象构造另一个对象
函数的参数是类的对象
返回值是类
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14class zjy
{
}
void zjy2()
{
zjy zjy3;//进行无参构造
return zjy3;//由于zjy3存在于栈区,所以函数结束会被回收,因此返回值是zjy3的复制体,此时调用了拷贝构造
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48class zjy
{
public:
int chg;
zjy(int n);
zjy();
~zjy();
zjy(zjy&obj);
};
zjy::zjy()
{
cout<<"无参构造"<<endl;
}
zjy::zjy(zjy &obj)
{
cout<<"拷贝构造函数"<<endl;
}
zjy::~zjy()
{
cout<<"析构函数"<<endl;
}
zjy::zjy(int n)
{
chg=520;
n=chg;
cout<<n<<endl;
cout<<"带参构造函数"<<endl;
}
zjy func()
{
zjy obj;
return obj;
}
int main()
{
func();
zjy obj(0);
zjy chg=func();
system("pause");
return 0;
}第二个代码运行结果:
- 无参构造:
func
里面的obj
- 析构函数:函数调用完会释放内存,这里释放的是第一个obj,所以调用析构函数
- 带参构造:43行代码
- 无参构造:是因为用了chg来接收
由于上面结果不一致,重点参考下面的
- 无参构造:调用
test_func_2()
,从主调函数,进入被调函数,创建Monster obj
采用的是无参构造 - 拷贝构造1号:因为需要函数返回
obj
,但是函数里面的数据在函数完成时,会被释放,所以采用拷贝构造创建的副本obj
- 析构(1):当函数完成时,释放内存,调用析构函数释放原本的
obj
- 析构(2):由于没有接收
obj
,所以会在执行完76行释放返回的obj
副本 - 无参构造:78行调用函数(如上的无参构造)
- 拷贝构造1号:如上
- 析构(3):如上,第一个析构
- 析构(4):这里的析构和第二个析构不一样,这里的析构是因为,
main
完成了,释放monster
接收的obj
- 无参构造:
问题1:为什么第78行
Monster monster=test_func_2()
这里没有拷贝构造?- 没有东西去接收复制体时,系统会创建一个临时的对象,再用拷贝构造,将返回的
obj
,拷贝构造给临时变量 - 由于78行,有一个
monster
接收返回的obj
,系统优化,直接复制给monster
,所以不会调用拷贝构造
1
2
3
4
5
6
7
8
9
10
11
12
13
14zjy func()
{
return zjy();
}
int main()
{
func();
system("pause");
return 0;
}运行结果:
- 无参构造:因为这里在
return
后面创建了一个zjy(匿名对象)
,相当于在函数外边创建了一个对象,这里不会采用拷贝构造,所以时无参构造 - 析构函数:因为没有接收对象,所以在49行的时候析构掉了
1
2
3
4
5
6
7
8
9
10
11
12
13
14zjy func()
{
return zjy();
}
int main()
{
//func();
zjy chg=func();
system("pause");
return 0;
}运行结果:
- 无参构造:因为调用
test_func_2()
,创建了一个匿名对象,采用无参构造(和上面的无参构造一样) - 析构:因为main函数结束,调用析构函数
- 没有东西去接收复制体时,系统会创建一个临时的对象,再用拷贝构造,将返回的
对于指针的构造:不能直接将指针指向那个地址,而是,创建一个新的内存用于存放原有的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20int main()
{
int *p=new int[5];
int *q=new int[5];
for(int i=0;i<5;i++)
{
p[i]=i;//可以相当于创建了一个数组,对于数组的存储可以用arr[i]=int类型
}
for(int i=0;i<5;i++)
{
q[i]=p[i];
}
for(int i=0;i<5;i++)
{
cout<<q[i]<<"\t";
}
system("pause");
return 0;
}浅拷贝和深拷贝
如何防止默认拷贝的发生(浅拷贝)?
函数
https://tsy244.github.io/2023/03/26/cpp/函数/