美文网首页
C++11部分特性

C++11部分特性

作者: TACITURNLY | 来源:发表于2016-08-18 20:36 被阅读0次

    预定义宏

    1. func预定义标识符

    功能:返回所在函数的名字
    C++11中甚至允许在类或结构体中使用:

    #include<iostream>
    using namespace std;
    
    class TestStruct {
    public:
      TestStruct () : name(__func__) {}
      const char *name;
    }; 
    
    int main() {
      TestStruct ts;
      cout << ts.name <<endl; 
    }
    

    原理:编译器隐式地在函数定义后定义func表示符
    所以需要注意的是func不能作为函数参数的默认值,因为在参数声明的时候,func还没有被定义

    void testFun(string func_name = __func__) {};  //compile error
    

    2.宏__cplusplus

    C++11的__cplusplus被预定义为201103L,可以用

    #ifdef __cplusplus < 201103L
        #error "please use C++11 implementation"
    #endif
    

    进行检测

    静态断言

    assert函数是在运行时进行断言,而当需要在编译时断言则需要使用静态断言,在C++11中,引入了static_assert,接受两个参数,static_assert ( bool_constexpr , message )一个是断言表达式(通常返回bool值),一个是警告信息

    当然,利用“不能除以0”的性质也可以实现静态断言,但效果明显没有C++11标准中的好(毕竟标准直接报错警告信息,而这样实现只会报不能/0,这样还会增加调试难度)

    #include<iostream>
    #include<cstring>
    using namespace std;
    
    #define assert_static(e) \
      do{ \
         enum{ assert_static__ = 1/ (e) }; \
      }while (0)
      
    template <typename T, typename U> int bit_copy(T&a, U& b){
      assert_static(sizeof(b) == sizeof(a));
    }
      
    int main(){
      int a = 1;
      double b = 3;
      bit_copy(a,b);
    }
    

    noexcept修饰符与noexcept操作符

    noexcept比throw()在效率上会高一些,在 C++11中,noexcept替代了throw()

    noexcept修饰符

    noexcept修饰符有两种形式,一种是直接加上关键字noexcept,而另外一种则可以接受一个常量表达式作为参数
    void excpt_func() noexcept (常量表达式);
    量表达式的结果会被转换成一个bool类型的值。该值为true,表示函数不会抛出异常,反之,则有可能抛出异常。这里,不带常量表达式的noexcept相当于声明了noexcept(true),即不会抛出异常。
    在通常情况下,在C++11中使用noexcept可以有效地阻止异常的传播与扩散。

    noexcept操作符

    noexcept作为一个操作符时,通常可以用于模板。
    我的测试代码:

    #include<iostream>
    #include<cstring>
    using namespace std;
    
    class Test{
    public:
      Test() {
        throw 1;
        cout<<"constructor"<<endl;
      }
      ~Test() {
        cout<<"dtor"<<endl; 
      }
    };
    
    template <class T>
      void fun() noexcept(noexcept(T())) {
        throw 1;
      }
      
    int main(){
      try{
        fun<Test>(); 
      }
      catch(...){
        cout<<"caught"<<endl;  //caught
      }
      
      try{
        fun<int>(); 
      }
      catch(...){
        cout<<"caught"<<endl;  //terminate called after throwing an instance of 'int'
      }
      return 0;
    }    
    

    noexcept(noexcept(T()))中,第二个noexcept就是一个noexcept操作符。当其参数是一个有可能抛出异常的表达式的时候,其返回值为false,反之为true(实际noexcept参数返回false还包括一些情况,这里就不展开讲了)。
    对于测试代码中的例子,当模板实参为Test时,Test()可能抛出异常,所以这时候此时签名修饰符为noexcept(false),所以可以抛出异常
    而当模板实参为int的时候,noexcept(noexcept(T()))为noexcept(true),所以这时候试图抛出异常的话,会直接调用std::terminate终端程序的执行

    另外需要注意的是,析构函数默认为noexcept,delete函数默认为noexcept

    快速初始化成员变量

    C++11增加允许了使用=或者花括号{}的方式来初始化:
    struct init{ int a = 1; double b {1.2}; };
    这样的方式也叫就地初始化,然而有一个问题,这样的初始化方式与初始化列表是否冲突?
    当然不会冲突:

    class Test{
    public:
      Test(string ss = "234"):s(ss){}
      
      string s {"123"};
    };
    

    相关文章

      网友评论

          本文标题:C++11部分特性

          本文链接:https://www.haomeiwen.com/subject/duovsttx.html