首页 > 其他 > 详细

临时对象

时间:2020-06-15 00:55:01      阅读:51      评论:0      收藏:0      [点我收藏+]

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

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

 三、移动赋值运算符

Element&  operate=(Element &&  elem)  noexcept    // 也需要加noexcept 关键字
// 拿到对方内存的时候,需要将对方的指针置空

四、哪些情况下系统会帮我们合成移动构造函数和移动赋值运算符

1、不会!当有自己的拷贝构造函数拷贝赋值运算符或者析构函数(三者主要有其一),编译器将不会帮我们合成移动构造函数移动赋值运算符

所以有些类没有移动构造函数移动赋值运算符

2、如果没有自己的移动构造函数移动赋值运算符,那么系统会调用我们自己写的拷贝构造函数拷贝赋值运算符。

3、只有一个类没有定义自己的拷贝构造函数拷贝赋值运算符或者析构函数。且每个非静态成员都可以移动时,编译器才会为该类合成移动构造函数和移动赋值运算符。

什么叫可以移动:

(1)内置类型是可以移动的

(2)类类型,则这个类要有对应的移动操作相关的函数,就可以移动。

五、移动构造函数小结

(1)尽量给类增加移动构造和移动赋值运算符

(2)再不需要抛出异常的情况下一定要加 noexcept 关键字,保证该执行移动构造函数的时候不会去执行拷贝构造函数

(3)移动构造函数执行后,一定要记得给移动后的指针置空


 

临时对象

原文:https://www.cnblogs.com/zhiminzeng/p/13127428.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!