C++类封装(C++11)的相关笔记

一、创建C++类后,编译时会自动生成default构造函数、copy构造函数、赋值操作符、析构函数。

定义类时,请明确定义上述四个函数的性质:

clsA() = default; //明确告诉编译器使用默认生成的构造函数

clsA() = delete; //明确告诉编译器禁止使用构造函数

virtual ~clsA()=0;//明确告诉编译器为纯虚函数(C98版需要加{})

void opr2() final; //明确告诉编译器该函数不可被继承

void opr1() override; //明确告诉编译器该函数完全继承父类的定义

二、C++关键字explicit只能写在在声明中,不能写在定义中。

1、用于类型转换函数,例:explicit operator double() const { return d; }
调用时必须声明显式转换,static_cast<double>(f);

2、用于单操作数构造函数,则禁止构造函数的隐式转换。例:explicit A(const B& b) {}

3、用于拷贝构造函数,则这个类对象不能隐式调用,用于传参传递和函数返回值。同时禁止编译器自动调用拷贝初始化,还可以禁止编译器对拷贝函数的参数进行隐式转换。例:
explicit A(const A& a) {} //无法使用RVO返回值优化

三、显式RVO,显式NRVO,浅拷贝,深拷贝
A&& getVar() { return A(); } //浅拷贝,报警,返回局部变量的引用
A& getVar() { return A(); } //浅拷贝,报警,返回局部变量的引用
A getVar() { return A(); }//深拷贝,会进行显式RVO优化。
!!! 除类成员对象,任何时候不要返回引用,无论左值右值。

四、右值引用、拷贝构造、移动构造、拷贝赋值、移动赋值

1、移动构造是需要通过移动构造函数std::move来完成的。!!! 所以不建议使用移动构造,默认构造+RVO非常完美。

2、移动赋值,像下图这样使用:
void operator=(clsA&& a) noexcept { m_int = a.m_int; a.m_int = nullptr; }
//这样a对象在析构销毁时,因为指针为nullptr。而clsA自己m_int实际接管了a.m_int的指针

五、关于网上消息的谬论,不知道为啥这些未经验证就能发出来,C++本就复杂了,再鱼龙混杂,其心叵测。

1、explicit只能用于构造函数中。

2、int &&k = getVar(); //第二行语句中getVar()产生的临时对象不会像第一行代码那样,在表达式结束之后就销毁了,而是会被“续命”,它的生命周期将会通过右值引用得以延续,和变量k的生命周期一样长。

经测试,经编译器RVO优化没有临时对象,哪来的生命周期?而直接返回右值引用的临时对象,生命周期也是创建后复制传递后就销毁。

总结:C++的内存管理机制RAII已经很好用了,新增的右值引用功能有限(仅用于移动赋值),C++11改进更像是语法糖。但增加与编译器的沟通是好事,明确声明才会减少内存问题的发生和产生岐义。后面C++融入更多机制(所谓Modern C++),也只是便于管理、融合标准库、增强多线程的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值