C++01——类和对象_类的生存周期
已经报班学习了一年的C,C++,Linux,大二一年学会了很多东西,但刚升大三,看看身边的同学都在努力奋斗着,回想自己的学习成果,感觉真的很浅。所以决定把C++和Linux的知识,通过看录屏,重新学习一下,通过CSDN来记录知识点,也希望大家可以多交流指教。朋友圈学长,学姐进入阿里的,进入腾讯的,都挺羡慕的。感觉这些足以让我有动力更努力了。大三的我,开始吧。
类和对象:6个默认函数之四
生成对象(构造函数):步骤一,开辟对象的内存空间;步骤二,调用构造函数
销毁对象(析构函数):步骤一,调用析构函数;步骤二,释放对象所占空间
1.构造函数:初始化对象所占内存空间
2.析构函数:释放对象所占资源
3.拷贝构造函数:用一个已存在的对象来构造一个相同类型的新对象
形参必须使用引用对象:否则形参对象会死循环。
4.赋值运算符的重载函数
用一个已存在的对象给另一个相同类型已存在的对象赋值
形参要使用常引用
常引用的作用:1.防止实参被修改
扫描二维码关注公众号,回复:
11655578 查看本文章
2.接收隐式生成的临时对象
对象的生存周期
注:代码中的#if 0与#endif位置自己移动,每个/* */与代码组成一个例子。
//对象的生存周期
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
using namespace std;
class Object
{
public:
Object(int num)
{
cout << "Object::Object(int)" << endl;
mname = new char[1];
mnum = num;
}
Object(char* name)//构造函数
{
cout << "Object::Object()" << endl;
mname = new char[strlen(name) + 1];
strcpy(mname,name);
mnum = strlen(mname) + 1;
}
Object(const Object& rhs)//拷贝构造函数
{
cout << "Object::Object(Object)" << endl;
mname = new char [strlen(rhs.mname) + 1];
strcpy(mname,rhs.mname);
mnum = rhs.mnum;
}
Object& operator=(const Object& rhs)//赋值运算符的重载函数
{
cout << "Object::operator(Object)" << endl;
if(this != &rhs )
{
delete[] mname;
mname = new char[strlen(rhs.mname) + 1];
strcpy(mname,rhs.mname);
mnum = rhs.mnum;
}
return *this;
}
~Object()//析构函数
{
cout << "Object::~Object()" << endl;
delete[] mname;
mname = NULL;
}
private:
char* mname;
int mnum;
};
void Func1( Object obj)
{
Object tmp (obj);
}
void Func2( Object& obj)
{
Object tmp (obj);
}
int main()
{
/*
形参是对象类型 建议大家使用引用
效率高:少了空间开辟,少了两个函数调用
//Func1(无引用):实参传形参时,形参生成开辟内存,生成对象二obj
//Func2(有引用):不会有形参对象生成
总结:当调用Func1时,调用三个构造函数;
当调用Func2时,调用两个构造函数。(无形参对象生成)
*/
Object ob1("object");//生成对象一ob1
Func1(ob1);//实参传形参时,形参生成开辟内存,生成对象二obj,生成对象三tmp
#if 0
Func2(ob1);
/*
new,在堆上开辟内存,需要手动释放,在delete调用时,调用析构函数进行释放
调用函数顺序:第一句调用构造函数;
第二句调用构造函数;
第一句调用析构函数。(第二句delete调用点时调用析构)
*/
Object obj1("object1");
Object* pobj = new Object("object heap");//栈上的指针指向堆上的对象
/*
=右边是临时对象的生成,临时对象应该在“;”结束之前调用析构函数
第二行的调用析构函数改变原因:引用会提升临时对象的生存周期,
提升到从调用点到main函数结束,与引用对象的生存周期相同。
调用函数顺序:第一句调用构造函数;
第二句调用构造函数;
第一句调用析构函数。(第二句main函数结束之前,调用析构函数)
*/
Object* pobj = &Object("object");
Object& pobj1 = Object("object");
/*
等号右边显示调用一个临时对象
临时对象在这句中的作用:为了生成新对象
当临时对象是为了生成新对象时,以生成临时对象的方式生成新的对象,编译器优化掉临时对象的生成
总结:只调用一个构造函数,一个析构函数。(等号左边的临时对象的生被优化掉)
*/
Object obj = Object("object");//只生成一个对象
/*
等同于: Object obj ("object");
总结:调用一个构造函数,一个析构函数
*/
Object obj ="object";
/*
等号右边为逗号表达式,选择最后一个数据,则构造10的类型函数,所以选择调用整形的构造函数。
并且生成临时对象时优化,生成一个对象
总结:调用一个构造函数,一个析构函数
*/
Object obj = (Object)("object",10);
#endif
}
生命周期的例题:
//对象的生存周期的例题
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
using namespace std;
class Test
{
public:
Test(double c = double())
{
cout << "c:" << c <<endl;
ma = mb = 0;
mc = c;
cout << "Test(double):" << mc << endl;
}
Test(int a,float b,double c)
{
ma = a;
mb = b;
mc = c;
cout << "Test(int,float,double):"<< mc << endl;
}
Test (const Test& rhs)
{
ma = rhs.ma;
mb = rhs.mb;
mc = rhs.mc;
cout << "Test(Test):"<< mc << endl;
}
Test& operator=(const Test& rhs)
{
if (this != &rhs)
{
ma = rhs.ma;
mb = rhs.mb;
mc = rhs.mc;
}
cout << "opertaor=(Test):"<< mc << endl;
return* this;
}
~Test()
{
cout << "~Test()" << mc << endl;
}
private:
int ma;
float mb;
double mc;
};
Test gtest1(10,20.1f,1.1);
static Test gtest2(10,20.1f,1.2);
int main()
{
Test ltest1(10,20.2f,2.1);
Test ltest2(2.2);
Test ltest3 = ltest1;
ltest2 = ltest3;
static Test ltest4(10,20.3f,2.4);
Test ltest5 = Test(20,20.1f,2.5);
ltest5 = Test(30,30.1f,2.5);
Test ltest6 = Test(20,20.1f,2.6);
ltest6 = (Test)(30,30.1f,2.6);
Test* ptest7 = new Test(20,20.4f,2.7);
Test* ptest8 = &Test(20,20.4f,2.8);
Test& ptest9 = Test(20,20.4f,2.9);
delete ptest7;
return 0;
}
Test gtest3(10,20.1f,1.3);
static Test gtest4(10,20.1f,1.4);
代码运行结果与解析如下: