【深入理解C++11:C++新特性解析】第5章 提高类型安全 测试代码整理

目录

 

5-1.通过namespace分割了全局空间但是namespace中的成员依旧被enum成员污染的举例

5-2.枚举成员被隐式转换之后无法通过编译的例子

5-3.用令人眼花缭乱的方法封装不同的枚举类达到避免被隐式转换的目的

5-4.编译器会更具数据类型的不同对enum应用不同的数据长度

5-5.用一个例子来说明强制枚举类型的用法

5-6.为强类型枚举显式指定底层基本类型保证各编译器输出一致

5-7附近.C++11中枚举类型在作用域做了拓展

5-7.由于enum class是强类型作用域的,所以匿名的enum class很可能什么也做不了

5-8.一个简单说明C++11中的智能指针unique_ptr和shared_ptr使用方法的例子

5-9.一个简单说明C++11中的智能指针weak_ptr使用方法的例子

5-10.一个简单说明移动指针可能触发垃圾回收的例子

5-11.什么时候会触发垃圾回收机制呢?这个代码是不可控不安全的

5-12.declare_reachable显式告诉垃圾回收器不要去回收对应内存


5-1.通过namespace分割了全局空间但是namespace中的成员依旧被enum成员污染的举例

#include <iostream>
using namespace std;
namespace T{
     enum Type{General,Light,Medium,Heavy};
}

namespace {
     enum Category{General = 1,Pistol,MachineGun,Cannon};
}
int main(){
    T::Type t = T::Light;
    if( t == General) // 忘记使用namespace
        cout<<"General Weapon" << endl;
    return 0;
}
/*
   编译选项:g++ -std=c++11 5-1-1.cpp
   代码清单: 5-1
   代码功能:通过namespace分割了全局空间但是namespace中的成员依旧被enum成员污染的举例
*/

5-2.枚举成员被隐式转换之后无法通过编译的例子

#include <iostream>
using namespace std;

enum Type{General,Light,Medium,Heavy};

// enum Category{Pistol,MachineGun,Cannon}; // 无法编译通过,重复定义
enum Category{Pistol,MachineGun,Cannon};

struct Killer{
    Killer(Type t,Category c):type(t),category(c){}
    Type type;
    Category category;
};
int main(){
    Killer cool(General,MachineGun);
    if(cool.type >= Pistol) // 用错类型了,g++下会报警告,但是能够编译通过
            cout << "It is not a pistal" << endl;
    cout << is_pod<Type>::value << endl;     // 1
    cout << is_pod<Category>::value << endl; // 1
    return 0;
}
/*
   编译选项:g++ -std=c++11 5-1-1.cpp
   代码清单: 5-2
   代码功能:通过namespace分割了全局空间但是namespace中的成员依旧被enum成员污染的举例
*/

5-3.用令人眼花缭乱的方法封装不同的枚举类达到避免被隐式转换的目的

#include <iostream>
using namespace std;
class Type{
   public:
        enum type{general,light,medium,heavy};
        type val;
    public:
         Type(type t):val(t){}
         bool operator >=(const Type & t) {return val>= t.val}
         static const Type General,Light,Medium,Heavy;
};
const Type Type::General(Type::general);
const Type Type::Light(Type::light);
const Type Type::Medium(Type::medium);
const Type Type::Heavy(Type::heavy);

class Category{
    public:
        enum category{pistol,machineGun,cannon};
        category val;
    public:
        Category(category c):val(c){}
        bool operator >= (const Category &c){return val >= c.val;}
        static const Category Pistol,MachineGun,Cannon;   
};
const Category Category::Pistol(Category::pistol);
const Category Category::MachineGun(Category::machineGun);
const Category Category::Cannon(Category::cannon);

struct Killer{
    Killer(Type t,Category c):type(t),category(c){}
    Type type;
    Category category;
};

int main(){
    Killer notCool(Type::General,Category::MachineGun);// 使用类型包装后的enum
    if(notCool.type >= Type::General) 
        cout <<"It is not general" <<endl;
    //if(notCool.type >= Category::Pistol) // 此处编译不能通过
    //    cout <<"It is not pistal" <<endl;
    cout << is_pod<Type>::value << endl;
    cout << is_pod<Category>::value << endl;
    return 0;
}

/*
   编译选项:g++ -c 5-1-3.cpp -c -std=c++11
   代码清单: 5-3
   代码功能:用令人眼花缭乱的方法封装不同的枚举类达到避免被隐式转换的目的
*/

5-4.编译器会更具数据类型的不同对enum应用不同的数据长度

#include <iostream>
using namespace std;
enum C {C1=1,C2 = 2};
enum D {D1=1,D2 = 2,Dbig = 0xFFFFFFF0u};
enum E {E1=1,E2 = 2,Ebig = 0xFFFFFFFFFLL};
int main(){
    cout << sizeof(C1)<<endl;   // 4
    cout << Dbig<<endl;         // 不同的编译器输出可能不同,g++输出4294967280,Visyual C++输出-16
    cout << sizeof(D1)<<endl;   // 4
    cout << sizeof(Dbig)<<endl; // 4
    cout << Ebig<<endl;         // 68719476735
    cout << sizeof(E1)<<endl;   // 8
    return 0;
}

/*
   编译选项:g++ -c 5-1-4.cpp -c -std=c++11
   代码清单: 5-4
   代码功能:编译器会更具数据类型的不同对enum应用不同的数据长度
*/

5-5.用一个例子来说明强制枚举类型的用法

#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;// 编译失败,必须使用强类型名称
   if(t == Category::General)// 编译失败,必须使用Type中的General
       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;
   cout << is_pod<Category>::value << endl;
   return 0;
}
/*
   编译选项:g++ -c 5-1-5.cpp -c -std=c++11
   代码清单: 5-5
   代码功能:用一个例子来说明强制枚举类型的用法
*/

5-6.为强类型枚举显式指定底层基本类型保证各编译器输出一致

#include <iostream>
using namespace std;
enum class C:char {C1=1,C2 = 2};
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;
}

/*
   编译选项:g++ -c 5-1-6.cpp -c -std=c++11
   代码清单: 5-6
   代码功能:为强类型枚举指定底层基本类型保证各编译器输出一致
*/

5-7附近.C++11中枚举类型在作用域做了拓展

enum Type{G,L,M,H};
Type t1 = G;
Type t2 = Type::G;

/*
   编译选项:g++ -c 5-1-7-1.cpp -c -std=c++11
   代码清单: 5-7附近的例子
   代码功能:C++11中枚举类型在作用域做了拓展
*/

 

5-7.由于enum class是强类型作用域的,所以匿名的enum class很可能什么也做不了

enum class {General,Light,Medium,Heavy} weapon;
int main(){
    weapon = General;
    bool b = (weapon == weapon::General);
    return 0;
}
/*
   编译选项:g++ -c 5-1-7-2.cpp -c -std=c++11
   代码清单: 5-7
   代码功能:由于enum class是强类型作用域的,所以匿名的enum class很可能什么也做不了
*/

5-8.一个简单说明C++11中的智能指针unique_ptr和shared_ptr使用方法的例子

#include <memory>
#include <iostream>
using namespace std;
int main(){
   unique_ptr<int> up1(new int(11));// 无法复制的unique_otr
   //unique_ptr<int> up2 = up1;     // 不能通过编译
   cout <<*up1<<endl;               // 11
   unique_ptr<int> up3 = move(up1); // 现在的up3是数据唯一的unique_ptr智能指针
   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
   return 0;
}

/*
   编译选项:g++ 5-2-1.cpp -c -std=c++11
   代码清单: 5-8
   代码功能:一个简单说明C++11中的智能指针unique_ptr和shared_ptr使用方法的例子
*/

5-9.一个简单说明C++11中的智能指针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;               // 22
   cout<< *sp2 <<endl;               // 22
   Check(wp);                        // still 22
   sp1.reset(); 
   cout<< *sp2 <<endl;               // 22
   Check(wp);                        // still 22
   sp2.reset();                      // pointer is invalid.
   Check(wp);   
   return 0;
}

/*
   编译选项:g++  5-2-2.cpp -std=c++11
   代码清单: 5-9
   代码功能:一个简单说明weak_ptr使用方法的例子
*/

5-10.一个简单说明移动指针可能触发垃圾回收的例子

#include <iostream>
using namespace std;
int main(){
   int * p = new int;
   cout <<hex<<p << endl;
   p += 10;                // 移动指针,可能导致垃圾回收器对内存进行回收
   cout <<hex<<p << endl;
   p -= 10;                // 移动指针,可能导致回收原来指向的内存
   cout <<hex<<p << endl;
   *p = 10;                // 再次使用原来相同的指针可能无效,灾难性的,此处我的编译器上没有出错   
   cout <<dec<<*p << endl;
   return 0;
}
/*
   编译选项:g++ 5-2-3.cpp -std=c++11
   代码清单: 5-10
   代码功能:一个简单说明移动指针可能触发垃圾回收的例子
*/

5-11.什么时候会触发垃圾回收机制呢?这个代码是不可控不安全的

#include <unistd.h>
#include <iostream>
using namespace std;
int main(){
   int *p = new int;
   cout << hex << p <<endl;
   int *q = (int*)(reinterpret_cast<long long>(p)^2012);// q隐藏了p
   cout << hex << q << endl; // 做了一些其他工作,垃圾回收器可能已经回收了p指向的对象,什么时候会触发垃圾回收机制启动呢?
   q = (int*)(reinterpret_cast<long long>(q)^2012); // 用可逆的异或运算将p恢复回来,这里的p==q 
   cout << hex << q << endl;
   *q = 10;// 这里的*q=10可能是灾难性的
   cout << dec << *q << endl;
   return 0;
}
/*
   编译选项:g++ 5-2-4.cpp -std=c++11
   代码清单: 5-11
   代码功能:什么时候会触发垃圾回收机制呢?
*/

5-12.declare_reachable显式告诉垃圾回收器不要去回收对应内存

#include <memory>
using namespace std;
int main(){
   int *p = new int;
   declare_reachable(p); // 在p被隐藏之前声明为可达的
   int *q = (int*)((long long)p ^ 2012);
   q = undeclare_reachable<int>((int*)((long long)p ^ 2012));// 解除可达声明
   *q = 10; 
   return 0;
}
/*
   编译选项:g++ 5-2-5.cpp -std=c++11
   代码清单: 5-12
   代码功能:declare_reachable显式告诉垃圾回收器不要去回收对应内存
*/

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值