你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

C++ 对象应用优化的几点总结

2021/12/30 15:03:42

C++ 对象应用优化

文章目录

    • C++ 对象应用优化
      • 编译器的优化
      • 三条对象优化的规则
      • 右值引用优化 —— 移动拷贝构造、移动赋值重载
      • move语义与完美转发

编译器的优化

	/*	
	C++编译器对于对象构造的优化:用临时对象生成新对象的时候,临时对象
	就不产生了,直接构造新对象就可以了
	*/
	Test t4 = Test(20);

	// 显式生成临时对象
	t4 = Test(30);
	t4 = (Test)30; // int->Test(int)

	// 隐式生成临时对象
	t4 = 30; // Test(30) int->Test(int)    char*->Test(char*)

三条对象优化的规则

  • 函数参数传递过程中,对象优先按引用传递,不要按值传递
  • 函数返回对象的时候,应该优先返回一个临时对象,而不要返回一个定义过的对象
  • 接收返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收
    会产生临时对象
// 不能返回局部的或者临时对象的指针或引用


Test GetObject(Test &t) 
{
	int val = t.getData();
	/*Test tmp(val);
	return tmp;*/
	// 返回临时对象
	return Test(val); 
}
int main()
{
	Test t1;
	Test t2 = GetObject(t1);
	//t2 = GetObject(t1); // 产生临时对象
	return 0;
}

右值引用优化 —— 移动拷贝构造、移动赋值重载

int main()
{
	// 右值引用
	int a = 10;
	int &b = a; // 左值:有内存、有名字   右值:没名字(临时量)、没内存
	//int &&c = a; // 无法将左值绑定到右值引用

	/*
	int tmp = 20;
	const int &c = tmp;
	*/
	const int &c = 20; // 不能用左值引用绑定一个右值
	/*
	int tmp = 20;
	int &&d = tmp;
	*/
	int &&d = 20; // 可以把一个右值绑定到一个右值引用上
	CMyString &&e = CMyString("aaa");

	int &f = d; // 一个右值引用变量,本身是一个左值

	return 0;
}
// 带右值引用参数的拷贝构造
	CMyString(CMyString &&str) // str引用的就是一个临时对象
	{
		cout << "CMyString(CMyString&&)" << endl;
		mptr = str.mptr;
		str.mptr = nullptr;
	}
	// 带左值引用参数的赋值重载函数
	CMyString& operator=(const CMyString &str)
	{
		cout << "operator=(const CMyString&)" << endl;
		if (this == &str)
			return *this;

		delete[]mptr;

		mptr = new char[strlen(str.mptr) + 1];
		strcpy(mptr, str.mptr);
		return *this;
	}
	// 带右值引用参数的赋值重载函数
	CMyString& operator=(CMyString &&str) // 临时对象
	{
		cout << "operator=(CMyString&&)" << endl;
		if (this == &str)
			return *this;

		delete[]mptr;

		mptr = str.mptr;
		str.mptr = nullptr;
		return *this;
	}

move语义与完美转发

	/*void push_back(const T &val) // 接收左值
	{
		if (full())
			expand();

		_allocator.construct(_last, val);
		_last++;
	}

	void push_back(T &&val) // 接收右值 一个右值引用变量本身还是一个左值
	{
		if (full())
			expand();

		_allocator.construct(_last, std::move(val));
		_last++;
	}*/

	// void push_back(CMyString &val)
	// CMyString&& + && = void push_back(CMyString&&val)
	template<typename Ty> // 函数模板的类型推演 + 引用折叠
	void push_back(Ty &&val) //Ty CMyString& + && = CMyString&
	{
		if (full())
			expand();

		// move(左值):移动语义,得到右值类型   (int&&)a
		// forward:类型完美转发,能够识别左值和右值类型
		_allocator.construct(_last, std::forward<Ty>(val)); // std::forward 完美转发
		_last++;
	}