施磊C++ | 进阶学习笔记 | 1.对象的应用优化、右值引用的优化

发布于:2024-10-17 ⋅ 阅读:(8) ⋅ 点赞:(0)

一.对象的应用优化、右值引用的优化

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;
}
课后练习:

image-20241009213117219

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博客进行学习