临时量
· 内置类型生成的临时量是常量(临时量,寄存器带出来)。
· 自定义类型生成的临时量是变量 ,在内存中。
· 隐式生成生成的临时量是常量 ,显式生成生成的临时量是变量 。
临时对象
临时对象是系统临时分配的对象,在没主动声明所需对象而又使用其功能时产生的。
何时产生临时对象:
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();等价
先调用带有一个参数的构造函数,生成临时对象,这个临时对象生成的目的是为了生成新对象,故有优化。