C++11常用特性学习-类型安全(强类型枚举类/智能指针)

C98和C03对在构建复杂系统时已经可以胜任,并且在作用域、安全等方面已经可以满足现有的需求。C11增加的部分主要针对于程序员容易犯错误的部分进行优化,使其专心于C++项目本身而不是Cplusplus本身,C11主要在枚举和指针方面做出改进,使其天然的“安全”。

强类型枚举类

C++目前较长使用的分门别类的方法主要有三种:命名枚举:enum Gender { Male, Female}+匿名枚举:enum { Male, Female};宏定义:#define Male 0; 静态常量:const static int Male = 0。
枚举在有namespace的命名空间内使用稍显麻烦,一般编译器不会报错,且不同枚举内名称不能相同,一般在比较时转换为int类型,没有类型的属性(枚举可以直接和int比较和转换);宏定义简单替换,只在预处理有意义;静态常量:const static占用储存空间(详见:《深入理解C++11新特性解析与应用》第5.1节)。
C11引进一种新的枚举类型,即枚举类/强类型枚举,在enum后加关键字class即可。
如:enum class Type { General,Light,Medium,Heavy);
优点如下:
◆強作用域,强类型枚举成员不会输出到其父类作用空间;
◆强制转换限制,无法隐式的转换类型,但可以(int)X的形式转换;
◆枚举类可以指定底层数据类型:enum clsaa Type:char{General, Light, Medium, Heavy};

C11之前内存和指针可以改进的地方

C98/03指针(显示管理)从编码角度说,容易出现以下状况:
1 . 内存泄露:不需要使用的内存未释放,导致程序内存集聚增加。
2 . 野指针:已经释放内存的指针为设为NULL,依然使用,指向为知区域,1导致无法预料的错误;
3 . 重复释放:程序试图释放已经释放的内存单元或者已经重新分配的内存单元,造成重复释放,导致无法预计错误,Linux系统中这种情况打印出大量的错误;

让程序员摆脱内存管理的细节,专注于业务和逻辑,是智能指针的设计初衷,但是auto_ptr指针在使用时不太符合C11的左值等原则,不能调用delete等,所以在C++11中auto_ptr被废弃,引入:unique_ptr、share_ptr和weak_ptr等职能指针来自动回收堆分配的对象。

智能指针总结概论

在现代 C++ 编程中,标准库包含智能指针,该指针用于确保程序不存在内存和资源泄漏且是异常安全的。
unique_ptr
只允许基础指针的一个所有者。 除非你确信需要 shared_ptr,否则请将该指针用作 POCO 的默认选项。 可以移到新所有者,但不会复制或共享。 替换已弃用的auto_ptr。 与 boost::scoped_ptr 比较。 unique_ptr 小巧高效;大小等同于一个指针且支持 rvalue 引用,从而可实现快速插入和对 STL 集合的检索。 头文件:。

shared_ptr
采用引用计数的智能指针。 如果你想要将一个原始指针分配给多个所有者(例如,从容器返回了指针副本又想保留原始指针时),请使用该指针。 直至所有shared_ptr 所有者超出了范围或放弃所有权,才会删除原始指针。 大小为两个指针;一个用于对象,另一个用于包含引用计数的共享控制块。 头文件:。

weak_ptr
结合 shared_ptr 使用的特例智能指针。 weak_ptr 提供对一个或多个 shared_ptr 实例拥有的对象的访问,但不参与引用计数。 如果你想要观察某个对象但不需要其保持活动状态,请使用该实例。 在某些情况下,需要断开 shared_ptr 实例间的循环引用。 头文件:

#include <memory>
#include <iostream
using namespace std;
void Check(weal_ptr<int> &wp);
int main(){

//unique_ptr
    unique_ptr<int> up1(new int(11));
        //  unique_ptr<int> up2 = up1;  //不能编译通过
    unique_ptr<int> up3 = move(up1);

    cout << *up3 < <endl; //11
    cout<< *up3 << endl; //运行错误
    up3.reset();    //显示释放内存
    up1.reset();    //不会导致运行错误

// shared_ptr
    shared_ptr<int> sp1(new int(22));
    shared_ptr<int> sp2 = sp1;

    cout<< *sp1 << endl; //22
    cout<< *sp2 << endl; //22
    sp1.reset();
    cout<< *sp2 << endl; //22

//  weal_ptr
    shared_ptr<int> sp3(new int(33));
    shared_ptr<int> sp4 = sp3;
    weak_ptr<int> wp = sp3; //    指向 shared_ptr<int>对象;
    cout<< *sp3 << endl; //33
    cout<< *sp4 << endl; //33
    check(wp);      //still 33

     sp3.reset();
     cout<< *sp3 << endl; //33
    check(wp);      //still 33
     sp4.reset();
     check(wp);     //pointer is invalid
}

void Check(weak_ptr<int> &wp) {
    shared_ptr<int> sp = wp.lock(); //转换为share_ptr<int>
    if (sp != nullptr)
        cout << "stil" << *sp << endl;
    else
        cout << "pointer is invalid"<<endl;
}

程序解析:
uique_ptr和shared_ptr均来自自动释放对象的内存。指针重载了*符号,可以直接饮用该内存,当该对象析构或者调用reset成员函数时,指针都可能释放其拥有的堆内存。
uique_ptr与所指对象/内存空间绑定紧密,不能与其他uique_ptr共享所指向对象的内存。其“所有权”仅能通过标准库函数move来转移。一旦被转移,该指针失去所有权,再次引用其所有权会导致运行错误。
shared_ptr允许多个智能指针共享的“拥有”同一堆分配对象的内存。与uique_ptr不同,由于在实现上采用了引用计数,所以一旦一个shared_ptr放弃了对对象内存的“所有权”,其他shared_ptr对内存对象的引用并不会受到引线。只有在引用计数为零时,shared_ptr才会释放其堆内存的空间。
weak_ptr可以指向shared_ptr指向的对象内存,却并不拥有该内存。而使用weak_ptr成员lock(),则可返回其指向内存的一个shared_ptr:对象,且在所指对象内存已经无效时,返间指针空值nullptr。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值