根据之前的学习,我们知道,临时性对象的产生会消耗系统资源,我们学习临时性对象的整理和分析的 目的 就是怎么样 让这些 临时性对象少产生。
0.先来复习一下
产生临时对象的3中情况以及解决方案。
第一种:以值的方式给函数传递参数
class Teacher75 {
public:
Teacher75() {
cout << "Teacher75 构造函数" << this<< endl;
}
Teacher75(const Teacher75 & t) {
this->m_age = t.m_age;
cout << "Teacher75 copy 构造函数" << this<< " t = " << &t<<endl;
}
Teacher75& operator=(const Teacher75 & t) {
cout << "Teacher75 operator = 函数" << this<<endl;
this->m_age = t.m_age;
return *this;
}
int m_age;
};
//第一种:以值的方式给函数传递参数,这里参数是 Teacher75,
//当实参传递给形参的时候,会调用copy 构造函数,将实参传递copy 给形参
void getTeacher75age(Teacher75 t) {
cout << t.m_age << endl;
}
//第一种解决方案:
void getTeacher75agefix(Teacher75& t) {
cout << t.m_age << endl;
}
void main() {
Teacher75 t1;
t1.m_age = 28;
//第一种:以值的方式给函数传递参数
getTeacher75age(t1);
cout << "-----" << endl;
Teacher75 t2;
t2 = t1;
cout << "---使用引用的方式传递函数参数---" << endl;
getTeacher75agefix(t1);
}
第二种,函数返回临时对象的时候
//第二种,函数返回临时对象的时候
class Teacher76 {
public:
Teacher76() {
cout << "Teacher76 构造函数" << this << endl;
}
Teacher76(int age):m_age(age) {
cout << "Teacher76 构造函数" << this << endl;
}
Teacher76(const Teacher76 & t) {
this->m_age = t.m_age;
cout << "Teacher76 copy 构造函数" << this << " t = " << &t << endl;
}
Teacher76& operator=(const Teacher76 & t) {
cout << "Teacher76 operator = 函数" << this << endl;
this->m_age = t.m_age;
return *this;
}
~Teacher76() {
cout << "Teacher76 析构函数" << this << endl;
}
int m_age;
};
//问题,实际上是多一次 copy 构造函数调用
Teacher76 getTeacher76(){
Teacher76 temp; //Teacher76 构造函数000000A584D8F564
temp.m_age = 87;
return temp; //Teacher76 copy 构造函数000000A584D8F784 t = 000000A584D8F564
}
//解决方案,在可以的case下 直接return
Teacher76 getTeacher76fix() {
return Teacher76(87);
}
void main() {
getTeacher76();
// Teacher76 构造函数000000A584D8F564 temp 构造函数被调用
// Teacher76 copy 构造函数000000A584D8F784 t = 000000A584D8F564 return 时,会调用copy 构造函数
// 多了一个构造函数
// Teacher76 析构函数000000A584D8F564 // temp 被析构
// Teacher76 析构函数000000A584D8F784 //返回的copy出来的这个构造函数,没有接,因此也析构
cout << "断点在这里" << endl;
getTeacher76fix();
// Teacher76 构造函数00000085234FFB94
// Teacher76 析构函数00000085234FFB94
}
第三种 隐式类型转换
//第三种 隐式类型转换
int count(const string& source,char ch) {
return 8;
}
void main() {
char charshuzu[100] = "abcc";
int ncount = count(charshuzu,'a');
//这里调用为了能调用成功, charshuzu会被从char [100],隐式转换成 const string 。
//这会有隐式转换发生。
//改法:不要让C++编译器帮忙转,自己转。
string mystr = "mnv";
int ncount222 = count(mystr, 'a');
}
一。我们这里主要是研究一下,函数返回临时对象的情况,顺便研究一下,如果返回的是临时对象引用会怎么样
总结:返回的是对象,那么会有临时对象的产生,会调用 copy 构造。如果开发者自己正确的写了 copy函数(这里所谓正确的写了,是指的在有指针,或者引用的case 下,fix了浅拷贝问题),返回的对象是可以使用的。
但是如果返回的是 对象的引用,由于引用就是其本身,在函数结束的时候,就
//返回临时性对象 和 临时性对象 引用的 研究
class Teacher40{
public:
Teacher40() {
cout << "Teacher40 构造方法 this = " << this << endl;
}
~Teacher40() {
cout << "Teacher40 析构方法 this = " << this << endl;
}
Teacher40(const Teacher40 &obj) {
this->mage = obj.mage;
cout << "Teacher40 copy gouzao 方法 this = " << this << " obj = " << &obj << endl;
}
Teacher40 & operator=(Teacher40 &obj) {
cout << "Teacher40 copy gouzao 方法 this = " << this << " obj = " << &obj << endl;
this->mage = obj.mage;
return *this;
}
void print() {
cout << " mage = " << mage << " this = " << this << endl;
}
int mage;
};
Teacher40 getTeacher40() {
return Teacher40();
}
Teacher40 getTeacher401() {
Teacher40 tea; // 调用构造函数,tea这时候是0019FA2C
return tea; //return 的时候,会生成一个临时对象0019FA60,然后调用copy gouzao 将 0019FA2C的值赋值给0019FA60
//return执行完毕后,出了 getTeacher401的作用域,则会0019FA2C ,析构。
//那么这时候return 出去的就是一个临时对象 0019FA60
//Teacher40 构造方法 this = 0019FA2C
// Teacher40 copy gouzao 方法 this = 0019FA60 obj = 0019FA2C
// Teacher40 析构方法 this = 0019FA2C
// Teacher40 析构方法 this = 0019FA60
// duandian
}
Teacher40& getTeacher40yinyong() {
//return Teacher40();//build error。由于Teacher40()是一个右值,右值不能作为引用返回,
Teacher40 tea;
return tea;
//Teacher40 构造方法 this = 0073FDE8
// Teacher40 析构方法 this = 0073FDE8
// duandian new
}
void main41() {
getTeacher401();//这一条的时候 0019FA60 临时对象没有人接,立即就析构了
cout << "duandian" << endl;
}
void main42() {
getTeacher40yinyong();
cout << "duandian new" << endl;
}
Teacher40& getTeacher40yinyong2() {
//return Teacher40();//build error。由于Teacher40()是一个右值,右值不能作为引用返回,
Teacher40 tea;
tea.mage = 98;
return tea;
}
void main() {
Teacher40 tea = getTeacher40yinyong2();
cout << "tea.mage = " << tea.mage << endl;
cout << "duandian new 1" << endl;
//注意看的是:在返回局部变量引用的时候,局部变量会先析构,因此这么写mage不会被赋值为98
// Teacher40 构造方法 this = 038FFB68
// Teacher40 析构方法 this = 038FFB68
// Teacher40 copy gouzao 方法 this = 038FFC50 obj = 038FFB68
// tea.mage = 59767888
// duandian new 1
// Teacher40 析构方法 this = 038FFC50
}