C++:临时量&临时对象

临时量
      ·   内置类型生成的临时量是常量(临时量,寄存器带出来)。
      ·   自定义类型生成的临时量是变量 ,在内存中。
      ·   隐式生成生成的临时量是常量 ,显式生成生成的临时量是变量 。

临时对象
         临时对象是系统临时分配的对象,在没主动声明所需对象而又使用其功能时产生的。

何时产生临时对象

  1)以值的方式给函数传参;


#include<iostream>

class Test
{
public:

	Test(int a, int b)
	{
		std::cout << this << " :Test::Test(int,int)" << std::endl;
		ma = a;
		mb = b;
	}

	Test(int a)
	{
		std::cout << this << " :Test::Test(int)" << std::endl;
		ma = a;
		mb = 0;
	}

	Test()
	{
		std::cout << this << " :Test::Test()" << std::endl;
		ma = mb = 0;
	}

	Test(const Test& rhs)
	{
		std::cout << this << " :Test::Test(const Test&)" << std::endl;
		ma = rhs.ma;
		mb = rhs.mb;
	}

	Test& operator=(const Test& rhs)
	{
		std::cout << this << " :Test::operator=(const Test&)" << std::endl;
		if (this != &rhs)
		{
			ma = rhs.ma;
			mb = rhs.mb;
		}
		return *this;
	}

	~Test()
	{
		std::cout << this << " :Test::~Test()" << std::endl;
	}

	
private:
	int ma;
	int mb;
};

void getObject(Test lhs)
{

}

int main()
{
	Test test1(10, 20);//调用了带有两个参数的构造函数
	getObject(test1);//按值传递,已存在的对象生成一个相同类型的新(临时)对象,调用拷贝构造函数创造了一个副本。
	return 0;
}

打印结果

  

针对这种情况,将形参传入对象引用,因为引用只是对象的一个别名,不会产生临时对象,代码修改如下:

   

2)类型转换;


#include<iostream>

class Test
{
public:

	Test(int a, int b)
	{
		std::cout << this << " :Test::Test(int,int)" << std::endl;
		ma = a;
		mb = b;
	}

	Test(int a)
	{
		std::cout << this << " :Test::Test(int)" << std::endl;
		ma = a;
		mb = 0;
	}

	Test()
	{
		std::cout << this << " :Test::Test()" << std::endl;
		ma = mb = 0;
	}

	Test(const Test& rhs)
	{
		std::cout << this << " :Test::Test(const Test&)" << std::endl;
		ma = rhs.ma;
		mb = rhs.mb;
	}

	Test& operator=(const Test& rhs)
	{
		std::cout << this << " :Test::operator=(const Test&)" << std::endl;
		if (this != &rhs)
		{
			ma = rhs.ma;
			mb = rhs.mb;
		}
		return *this;
	}

	~Test()
	{
		std::cout << this << " :Test::~Test()" << std::endl;
	}

private:
	int ma;
	int mb;
};

int main()
{
	Test test1;//调用默认构造函数
	test1=10;//表达式左右类型不匹配,右边,已存在的对象先生成一个相同类型的新(临时)对象,调用带有一个参数的构造函数,
                 //然后这个已存在的(临时)对象赋值给相同类型的已存在的对象	
	return 0;
}

打印结果

针对这种情况,对main函数中的代码稍作修改,将不会产生临时对象,代码修改如下:

这其实是一种优化: 即临时对象生成的目的是为了生成新对象,则以生成临时对象的方式来生成新对象。

原因:当我们定义Test test1时,在main的栈中为test1对象创建了一个预留的空间。而我们用10调用构造时,此时的构造是在为test1预留的空间中进行的,因此减少了一次临时对象的创建。

    

3)函数需要返回一个对象时;

#include<iostream>

class Test
{
public:

	Test(int a, int b)
	{
		std::cout << this << " :Test::Test(int,int)" << std::endl;
		ma = a;
		mb = b;
	}

	Test(int a)
	{
		std::cout << this << " :Test::Test(int)" << std::endl;
		ma = a;
		mb = 0;
	}

	Test()
	{
		std::cout << this << " :Test::Test()" << std::endl;
		ma = mb = 0;
	}

	Test(const Test& rhs)
	{
		std::cout << this << " :Test::Test(const Test&)" << std::endl;
		ma = rhs.ma;
		mb = rhs.mb;
	}

	Test& operator=(const Test& rhs)
	{
		std::cout << this << " :Test::operator=(const Test&)" << std::endl;
		if (this != &rhs)
		{
			ma = rhs.ma;
			mb = rhs.mb;
		}
		return *this;
	}

	~Test()
	{
		std::cout << this << " :Test::~Test()" << std::endl;
	}

	int getValue()
	{
		return ma;
	}
private:
	int ma;
	int mb;
};

Test getObject(Test &lhs)
{
	Test tmp;//调用默认构造函数
	tmp = lhs.getValue();//表达式右边,调用带有一个参数的构造函数,生成临时对象,
	//然后已存在的对象赋值给相同类型的已存在的函数,调用赋值运算符重载函数,
	return tmp;//已存在的对象生成一个相同类型的新(临时)对象,调用拷贝构造函数。
}

int main()
{
	Test test1(10,20);//调用带有两个参数的构造函数
	getObject(test1);                   
	return 0;
}

打印结果

针对这种情况,直接返回对象,发现减少了一次构造函数调用,一次拷贝构造函数调用和一次赋值拷贝函数调用。

    

return lhs.getValue(); 与Test tmp=lhs.getValue();等价

先调用带有一个参数的构造函数,生成临时对象,这个临时对象生成的目的是为了生成新对象,故有优化。

猜你喜欢

转载自blog.csdn.net/free377096858/article/details/84797136