c++11--强枚举类型,智能指针

1.枚举
1.1. c++11之前的枚举
实例

#include <iostream>

enum Type{
    ONE,
    TWO,
    THREE
};

int main(){
    printf("sizeof_%d, ONE_%d\n", sizeof(ONE), ONE);
    return 0;
}

具备以下特点:
(1). 枚举值直接在父作用域可见。
(2). 枚举底层类型由编译器结合枚举成员数值自行决定。
(3). 枚举值支持隐式转换为整数类型。

称上述枚举为弱类型枚举。

1.2.c++的强类型枚举
实例

#include <iostream>

enum Type{
    ONE,
    TWO,
    THREE
};

enum class TypeNew : char{
    ONEN,
    TWON,
    THREEN
};

int main(){
    printf("sizeof_%d, ONE_%d\n", sizeof(ONE), ONE);
    printf("sizeof_%d,ONE_%d\n", sizeof(TypeNew::ONEN), TypeNew::ONEN);
    return 0;
}

在这里插入图片描述
具备以下特点:
(1). 枚举值直接在父作用域不可见,需要通过形如上述TypeNew::ONEN的形式。
(2). 枚举底层类型默认由编译器结合枚举成员数值自行决定,但可在定义时指定,如上述TypeNew底层类型为char
(3). 枚举值不支持隐式转换为整数类型。

称上述为强枚举类型。

1.3.c++11对原弱枚举类型的增强
(1). 支持对弱类型枚举指定底层存储类型。
(2). 对弱枚举类型值在父作用域可见,但也可通过枚举名::枚举值形式的使用。

1.4.弱枚举类型和#define的差异

#include <iostream>

#define ONE 1
enum type{
    ONE1
};

int main(){
    ONE;
    ONE+1;
    //int ONE = 1;
    //int ONE1 = 11;
    printf("one1_%d\n", ONE1);
    return 0;
}

上述采用#define时,mainint ONE = 1;会报错。因为#define在预处理阶段执行简单替换。
上述采用enum时,mainint ONE1 = 11;不会报错,后续打印的ONE111。因为enum在编译阶段,编译器结合场景智能选择。

2.智能指针
2.1.unique_ptr
实例

#include <memory>
#include <iostream>
using namespace std;

int main(){
    unique_ptr<int> up1(new int(11));
    //unique_ptr<int> up2 = up1;// err
    cout << *up1 << endl;
    unique_ptr<int> up3 = std::move(up1);
    cout << *up3 << endl;
    //cout << *up1 << endl;// err
    up3.reset();
    up1.reset();
    //cout << *up3 << endl;//err
    return 0;
}

(1). unique_ptr只支持移动拷贝构造,移动赋值。移动拷贝下,左边对象窃取右边对象资源。移动赋值下,左边对象先释放底层资源,再窃取右边对象资源。
(2). unique_ptr对象持有的资源被窃取后,后续不可再使用底层资源。
(3). 可使用reset显式释放底层资源。底层资源释放后,无法再使用。

unique_ptr一般用于只有一个持有者的资源的管理。

2.2.share_ptr
实例

#include <memory>
#include <iostream>
using namespace std;

int main(){
    shared_ptr<int> sp1(new int(22));
    shared_ptr<int> sp2 = sp1;
    cout << *sp1 << endl;
    cout << *sp2 << endl;
    sp1.reset();
    cout << *sp2 << endl;
    return 0;
}

(1). shared_ptr支持普通拷贝构造,普通赋值。普通拷贝构造下,左边对象和右边对象共享同一底层对象。普通赋值下, 左边对象原来底层对象的引用数先减1,再和右边对象共享同一底层对象(递增右边对象底层对象的引用数)。
(2). shared_ptr支持移动拷贝构造,移动赋值。移动拷贝构造下,右边对象底层资源被窃取到左边。意味着,右边对象此后不可再访问底层资源。底层资源引用数并未增加和减少。移动赋值下,先递减原来持有的底层资源引用数,再窃取右边对象的底层资源。意味着,右边对象此后不可再访问底层资源。但底层资源引用数并未增加和减少。
(3). 底层对象被多个shared_ptr共享时,通过共享的任一shared_ptr均可访问底层资源。单个shared_ptr释放资源只使得底层资源引用数减去1,当底层资源引用数变为0时,才实际释放。

2.3.weak_ptr
实例

#include <memory>
#include <iostream>

using namespace std;

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

int main(){
    shared_ptr<int> sp1(new int(22));
    shared_ptr<int> sp2 = sp1;
    weak_ptr<int> wp = sp1;
    cout << *sp1 << endl;
    cout << *sp2 << endl;
    Check(wp);
    
    sp1.reset();
    cout << *sp2 << endl;
    Check(wp);

    sp2.reset();
    Check(wp);
    return 0;
}

(1).可通过一个shared_ptr来构造一个weak_ptr
(2).weak_ptr仅仅指向底层资源,但无需递增底层资源引用数。
(3).通过weak_ptr执行lock,在指向的底层资源存在下,返回一个shared_ptr。在指向的底层资源不存在下,返回nullptr

3.智能指针的线程安全性
shared_ptr为例,该类型智能指针内部既要记录对象指针, 又要记录关于对象的引用。
其中通过原子变量操作对象引用来保持多线程下对象引用修改的原子性。
但我们执行诸如:

shared_ptr<int> pa(new int(1));
shared_ptr<int> pb(new int(10));
// 对pa需要:
// 递减原引用数
// 判断引用数是否为0,为0,则释放原对象指针
// 开始持有新的对象指针,新的引用数指针。
// 引用数加1。
pa = pb;

上述过程引用数修改是原子的,但整个操作是无锁的。
所以多线程下,需要对其加锁来保证整个过程互斥性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值