临时对象

一、产生临时对象的情况和解决方案

1、以传值的方式给函数传递参数

一般以传引用的方式来传递参数,可以少调一次构造函数和析构函数

2、类型转换生成的临时对象/隐式类型转换以保证函数调用成功

类型转换生成的临时对象

class Element
{
  int m_val;
  Element(int val = 10) : m_val(val) { }
}
Element ele;    // 调用一次默认构造函数
ele = 100;        //  调用一次构造函数, 调用一次拷贝赋值函数,调用析构函数
// 说明这句话会先构造一个临时变量,再将临时变量拷贝给ele
Element ele = 100; // 只会调用一次构造函数,直接用100来构造ele对象,构造在ele的预留空间中,不会生成临时对象,

隐式类型转换以保证函数调用成功

void Func(Element&  ele);
void Func2(const Element&  ele);
Func(100);   // 编译失败
Func2(100);   // 编译成功,系统会将100转换成一个临时对变量,再传给函数Func2
// C++只会为const引用隐式类型转换产生临时变量,而不会为非const引用产生临时变量

3、函数返回对象

Element Func()     // 该函数返回temp时,调用拷贝构造函数构造一个临时变量
{
    Element temp;  //  调用了一次构造函数
    return temp;     // 返回时会调用一次拷贝构造函数
}
Func();       // 当临时变量没有被接住的时候,会自动释放掉
Element ele = Func();  // 当临时变量被变量接住时,拷贝构造函数会直接在ele的预留空间中进行构造

// 函数优化。如果函数满足优化条件,即可以直接返回构造函数
Element Func() 
{
    return Element();    // 直接返回构造函数,
    // 这样操作只会调用一次构造函数来构造临时变量,不会调用拷贝构造函数,节省了一次拷贝和临时变量的析构
}

二、移动构造函数

// 格式:
Element(Element &&  elem)  noexcept : 初始化列表  
// noexcept:通知标准库我们这个移动构造函数不抛出任何异常(提高编译器效率),一般情况下,移动构造函数都要加这个关键字,可以提高编译器效率
// 当用户自定义了移动构造函数之后,原来函数返回值的临时变量调用拷贝构造函数的情况,都会自动调用移动构造函数,但是具体操作需要自己实现

相关推荐