一.对象的应用优化、右值引用的优化
文章目录
1.1 构造,拷贝,赋值,析构中的优化
#include<iostream>
using namespace std;
class test
{
public:
test(int a = 10) :ma(a) { cout << "test(int)" << endl; }
~test() { cout << "~test" << endl; }
test(const test& t) :ma(t.ma) { cout << "test(const &)" << endl; }
test& operator=(const test& t)
{
cout << "operator=" << endl;
ma = t.ma;
return *this;
}
private:
int ma;
};
int main()
{
test t1;//构造
test t2(t1);//拷贝
test t3 = t1;//拷贝
//临时对象生存周期就是这个语句
/*1.C++编译器对于对象构造的优化:用临时对象生成新对象的时候,临时对象就不产生了,直接构造新对象就可以了*/
test t4 = test(20);//相当于 test t4(20); 而不是先用临时对象构造,临时对象拷贝,然后临时对象析构,这样效率太低了就给优化了
cout << "--------" << endl;
t4 = t2;//赋值
//2.显式生成临时对象
//t4.operator=(const Test &t)这个临时对象会产生,因为要给参数t赋值,传参
t4 = test(30);// 依次调用 构造 赋值 析构
t4 = (test)30;//有合适的构造函数可以隐式的生成一个临时对象然后给t4,没有合适的就报错
//隐式生成临时对象
t4 = 30;//这3句等价
//3. 临时对象,指针和引用
// 指针指向临时对象不安全,但是引用是安全的
//p指向的是一个已经析构的临时对象,变成了野指针
test* p = &test(40);
//但是引用是可以的,因为是起了一个别名,给一块内存重新按了一个名字,就可以继续用,所以是安全的
const test& ref = test(50);
//4.全局变量是在main函数之前就完成了初始化的
//5.test *p1=new test(70) 调用一次构造函数 只有在delete的时候才调用析构
//6.test *p2=new test[2] 调用两次构造
//7.delete p1 调用析构然后才释放内存
//8.delete []p2 两次析构然后调用free释放整个内存
return 0;
}
课后练习:
1.2 函数调用过程中对象背后调用的方法
#include<iostream>
using namespace std;
class test
{
public:
test(int a = 10) :ma(a) { cout << "test(int)" << endl; }
~test() { cout << "~test" << endl; }
test(const test& t) :ma(t.ma) { cout << "test(const &)" << endl; }
test& operator=(const test& t)
{
cout << "operator=" << endl;
ma = t.ma;
return *this;
}
int getData() const { return ma; }
private:
int ma;
};
test GetObject(test t)//不能返回局部的或者临时对象的指针或引用
{
int val = t.getData();
test tmp(val);
return tmp;
}
int main()
{
//背后调用了哪些函数呢?
test t1;//1.test(int)
test t2;//2.test(int)
t2 = GetObject(t1);//3.test(const test&) t1->t 实参到形参是一个初始化的过程不是第一个赋值的过程,这里用t1初始化形参t
//4.test(int) 初始化tmp
// 5.test(const test&) tmp拷贝给一个临时对象
//5.tmp 析构
//6.t析构
//7.operator 赋值 给t2
//8.临时对象析构
//9.t2析构
//10.t1析构
return 0;
}
1.3 对象优化三原则
1.函数参数传递过程中,对象优先按引用传递,不要按照值传递(实参到形参不需要构造和析构函数调用)
2.函数返回对象的时候,优先考虑返回一个临时对象,而不是一个定义过的对象
//注意加了引用
test GetObject(test &t)//改成这样以后,调用会少了tmp的构造和析构,又少了两个调用
{
int val = t.getData();
return test(val);
}
3.接收函数返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按复制的方式接收
#include<iostream>
using namespace std;
class test
{
public:
test(int a = 10) :ma(a) { cout << "test(int)" << endl; }
~test() { cout << "~test" << endl; }
test(const test& t) :ma(t.ma) { cout << "test(const &)" << endl; }
test& operator=(const test& t)
{
cout << "operator=" << endl;
ma = t.ma;
return *this;
}
int getData() const { return ma; }
private:
int ma;
};
//注意,加了引用
test GetObject(test &t)//不能返回局部的或者临时对象的指针或引用
{
int val = t.getData();
test tmp(val);
return tmp;
}
int main()
{
//背后调用了哪些函数呢?
test t1;//1.test(int) 构造t1
test t2 = GetObject(t1);//2.test(int) 直接构造t2
//3.t2析构
//4.t1析构
//test t2;
//t2 = GetObject(t1);
return 0;
}
1.4 右值引用、move移动语意、完美转发
请转至C++11 新特性 学习笔记-CSDN博客进行学习