C++11:提高类型安全

来源:互联网 发布:wifi模块与单片机通信 编辑:程序博客网 时间:2024/06/14 08:09

1 强类型枚举

        C98的enum是非强类型作用域(在一个子命名空间定义的enum其父空间也可加enum成员,即enum相当于全局的,容易引起重复值),允许隐式类型转换(这条规则可以允许不同enum类型间相互比较成员值),占用存储空间及符号性不确定。C++11引入了强类型枚举enum class/struct具有以下特点:强作用域,子空间的枚举成员不会输出到父空间中; 转换限制,枚举成员的值不可以与整型隐式的相互转换,static_cast这样的强制转换还是可以的; 可以指定底层类型,即枚举成员的的底层存储类型可以自行指定,如char或unsigned int。使用如下:

#include <iostream>using namespace std;enum class Type { General, Light, Medium, Heavy };enum class Category { General = 1, Pistol, MachineGun, Cannon };int main() {    Type t = Type::Light;    t = General;                    // 编译失败,必须使用强类型名称,Type::General或Category::General    if (t == Category::General)     // 编译失败,必须使用Type中的General,Category和Type间不可以直接比较        cout << "General Weapon" << endl;    if (t > Type::General)          // 通过编译        cout << "Not General Weapon" << endl;    if (t > 0)                      // 编译失败,无法转换为int类型,禁止隐式转换        cout << "Not General Weapon" << endl;    if ((int)t > 0)                 // 通过编译,强制转换还是可以的        cout << "Not General Weapon" << endl;    cout << is_pod<Type>::value << endl;        // 1,C++11的强类型枚举仍是POD    cout << is_pod<Category>::value << endl;    // 1    return 0;}
       可以指定枚举成员的底层类型:

#include <iostream>using namespace std;enum class C : char { C1 = 1, C2 = 2};//若枚举值小于128,则可以char节省空间enum class D : unsigned int { D1 = 1, D2 = 2, Dbig = 0xFFFFFFF0U };int main() {    cout << sizeof(C::C1) << endl;   // 1    cout << (unsigned int)D::Dbig << endl;   // 编译器输出一致,4294967280    cout << sizeof(D::D1) << endl;     // 4    cout << sizeof(D::Dbig) << endl;   // 4    return 0;}


2 智能指针

      C++11的智能指针几乎是从Boost库的智能指针搬过来的,auto_ptr已经废弃了。unique_ptr表示不可以共享所指内存但是能通过move转让内存所有权。shared_ptr可以共享内存所有权,其采用引用计数,当计数为0时释放内存。weak_ptr是弱指针,其通常需要配合shared_ptr使用,其本身不会增加内存计数,但是可以通过提升lock操作变为shared_ptr若提升后的shared_ptr还存在则表明所管理的对象还存在,若提升后的shared_ptr为nullptr表明管理的对象已经不存在了。关于智能指针还是Boost的丰富些,除了这几个智能指针,boost还提供了管理数组的智能指针。

      unique_ptr和shared_ptr的使用例子:

#include <memory>#include <iostream>using namespace std;int main() {    unique_ptr<int> up1(new int(11));   // 无法复制的unique_ptr    unique_ptr<int> up2 = up1;          // 不能通过编译,这里是调用copy constructor,由于unique_ptr已经禁止copy constructor,但允许move constructor    cout << *up1 << endl;   // 11    unique_ptr<int> up3 = move(up1);    // 现在p3是数据的唯一的unique_ptr,move constructor         cout << *up3 << endl;   // 11    cout << *up1 << endl;   // 运行时错误    up3.reset();            // 显式释放内存    up1.reset();            // 不会导致运行时错误    cout << *up3 << endl;   // 运行时错误    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}
     weak_ptr和shared_ptr的例子:

#include <memory>#include <iostream>using namespace std;void Check(weak_ptr<int> & wp) {    shared_ptr<int> sp = wp.lock(); // 转换为shared_ptr<int>,weak_ptr提升为shared_ptr    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; // 指向shared_ptr<int>所指对象    cout << *sp1 << endl;   // 22    cout << *sp2 << endl;   // 22    Check(wp);              // still 22    sp1.reset();    cout << *sp2 << endl;   // 22    Check(wp);              // still 22    sp2.reset();    Check(wp);              // pointer is invalid}
     题外话:如何解决shared_ptr的循环引用?这里的循环引用指:假设对象A持有指向执行B的shared_ptr,对象B持有对象A的shared_ptr这样两个对象都不会被析构,解决的办法是:A持有B的shared_ptr,B持有A的weak_ptr   



3 垃圾回收

     C++11的垃圾回收仍没有成熟,所以该部分仅供参考娱乐,想了下还是不写该部分。现有的垃圾回收可能就是通过API指定内存可达(告诉垃圾回收器此部分内存不能回收),清除内存可达标志。



0 0
原创粉丝点击