C++11

__func__ 预定义标识符是预置在编译器中的宏,并不包含于任何头文件,所以直接调用即可,基本功能就是返回所在函数的名字

例子:

#include <iostream>
using namespace std;

const char* hello(){return __func__ ;}


int main()
{
cout<<"Standard Clib: "<<__STDC_HOSTED__<<endl;
cout<<"Standard C: "<<__STDC__<<endl;
//cout<<"ISO/IEC"<<_STDC_ISO_10646__<<endl
cout<<hello()<<endl;
}

实际上,按照标准定义,编译器会隐式地在函数的定义之后定义__func__标识符

比如上面的hello()函数等于:

const char* hello()
{
    static const char* __func__ = "hello";
    return __func__;
}

在C++11中,标准允许__func__使用在类或者结构体中

#include <iostream>
using namespace std;

class Test{
                const char* name;
        public: 
                Test():name(__func__){}
                const char* get(){return name;}
};

int main()
{
        Test t;
        cout<<t.get();
}

!!!但是将__func__用于函数参数的默认值是不允许的!这是因为在参数声明时,__func__还未被定义

_pragma 操作符

#pragma 是一条预处理的指令,是用来向编译器传达语言标准外的一些信息

例如:

#pragma once 会指示编译器,该头文件只被编译一次,和以下代码达到同样的效果

_Pragma 是与 #pragma功能相同的操作符

格式如下

__VA_ARGS__ 可以在宏定义的实现部分中替换省略号所代表的字符串

比如:

#define PR(...)printf(__VA_ARGS__)

例子:

#include <iostream>

#define LOG(...){\
                fprintf(stderr,"\n%s:Line %d :\t",__FILE__,__LINE__);\
                fprintf(stderr,__VA_ARGS__);\
                fprintf(stderr,"\n");\
}

int main()
{
        int x=3;
        LOG("x= %d" ,x);
}

运行结果:

long long 整形有两种 long long 和 unsigned long long 

long long 整形至少有64位,在写常数字面量时,可以使用LL(ll)后缀 来标识一个 long long 类型的字面量

而ULL (ull)表示一个unsigned long long  类型的字面量。 例子:

例子:

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

int main()
{
long long ll_min = LLONG_MIN;
long long ll_max = LLONG_MAX;
unsigned long long ull_max = ULLONG_MAX;

cout<< "min of long long "<<ll_min<<"\nmax of long long "<<ll_max <<"\nmax of unsigned long long "<<ull_max<<endl;
}

结果:

c++ 一共定义了下列5种标准的有符号整形

同时,每一种有符号整数都有一种对应的无符号整数版本,且有符号整形和其对应的无符号整形具有相同的存储空间大小。

比如 signed int 对应的无符号版本的整形是 unsigned int 

简而言之,c++11规定,扩展的整形必须和标准类型一样,有符号类型和无符号类型占用同样大小的内存空间。

当运算,传参等类型不匹配时,整形之间会发生隐式的转换

比如(int) a + (long long)b 通常会导致变量a 被提升为long long 类型后再与b进行运算

转化的规则由等级决定

1 长度越大的整形等级越高,比如long long int 的等级会高于int

2 长度相同的情况下,标准整形的等级高于扩展类型,比如long long int 和 _int64中,long long int 的等级更高

3 相同大小的有符号类型和无符号类型的等级相同 , long long int 和 unsigned long long int 的等级相同

当进行隐式的整形转换时,会按照低等级向高等级转换,有符号的转换为无符号的

比如定义_int128_t 为128位的有符号整数(对应的无符号整数_uint128_t),与任何短于它的类型的数据b进行运算时,都会导致b被隐式地转换为_int128_t的整形

C与C++混合编码

断言就是将一个返回值必须需要为真多判别式放在语句中,用于排除在设计的逻辑上不应该出现的情况。

<assert.h>头文件中提供了assert 宏,用于在运行时进行断言

如果不满足为真,则程序会异常终止

也可以通过定义NDEBUG 来禁止assert宏,assert的实现如下:

一旦定义了NDBUG宏,assert宏就将被展开为一条无意义的C语句

静态断言:

static_assert 接收两个参数,一个是断言表达式,一个则是警告信息

静态断言在编译时期就能完成,所以叫静态断言,static_assert的断言表达式的结果必须是在编译时期就可以计算的表达式

也就是必须是常量表达式

例子:

#include <iostream>
using namespace std;

#define assert_static(e)\
        do{\
                enum{assert_static__=1/(e)};\
        }while(0)

template <typename t,class u>
int bit_copy(t& a,u& b)
{
        static_assert(sizeof(b)==sizeof(a) , "the parameters of bit_copy must have same width");
}

int main()
{
        int a=0x2468;
        double b;
        bit_copy(a,b);

}

结果编译时报错:

noexcept 修饰符 和 noexcept 操作符

例如下面的异常声明表达式:

throw (int,double)是一个动态异常声明,指出了excpt_func()可能抛出的异常的类型。

noexcept 表示修饰的函数不会抛出异常。如果noexcept修饰的函数抛出了异常,编译器就可以选择直接调用terminate()函数来终止程序的运行(但这种调用方式也会有很多问题:无法保证对象的析构函数正常调用,无法保证栈的自动释放)

有下列两种声明模式:

常量表达式的结果会被转换成一个bool类型的值,该值为true,表示函数不会抛出异常,反之有可能抛出异常。

而不带常量表达式的noexcept相当于声明了noexcept(true),既不会抛出异常

例子:

#include <iostream>
using namespace std;
void Throw()
{       
        throw 1;
}
void NoBlockThrow()
{
        Throw();
}
void BlockThrow()noexcept
{
        Throw();
}

int main()
{
        try
        {
        Throw();
        }
        catch(int x)
        {
        cout<<"Found throw"<<x<<endl;
        }
        try
        {
        NoBlockThrow();
        }
        catch(int y)
        {
        cout<<"throw is not blocked"<<y<<endl;
        }
        try
        {
        BlockThrow();
        }
        catch(int z)
        {
        cout<<"Found throw 1.."<<endl;
        }
}

BlockThrow 本是不应该抛出异常的,但抛出了异常所以终止了程序运行

结果:

noexcept 作为一个操作符时可以用于模版:

fun函数是否是一个noexcept的函数,将由T()表达式是否抛出异常所决定。

第二个noexcept就是一个noexcept操作符,当其参数是一个有可能抛出异常的表达式时,则返回false ,否则返回true。

noexcept 的更大的作用是保证应用程序的安全,比如C++11默认将delete函数设置为noexcept就可以提高应用程序的安全性

同样c++11标准中让类的析构函数默认也是noexcept(true) 的。当然,如果程序员显示地为析构函数指定了noexcept。

例子:

#include <iostream>
using namespace std;

class A{
        public: 
        ~A()    
        {       
                cout<<"~A()"<<endl;
                throw 1;
        }
};

class B{
        public:
        ~B()noexcept(false)
                {
                cout<<"~B()"<<endl;
                throw 2;
                }
};

class C{
        private:
        A a;
        B b;
        public:
        ~C()
        {
                cout<<"~C()"<<endl;
        }
};

void funcA(){A a;}
void funcB(){B b;}
void funcC(){C c;}

int main()
{
        try{
                funcB();
           }
        catch(int x)
           {
                cout<<x<<endl<<"caught funcB."<<endl;
           }
        try{
                funcC();
           }
        catch(int y)
           {
                cout<<y<<endl<<"caught funcC."<<endl;
           }
        try{
                funcA();
           }
        catch(int z)
           {
                cout<<z<<endl<<"caught funcC."<<endl;
           }

}

快速初始化成员变量:

C++11 中,运行使用初始化列表,等号= ,花括号{}就地对非静态成员变量初始化。

但对非静态成员用()括号进行就地初始化,是不行的。

例子:

#include <iostream>
using namespace std;

struct Mem{
        Mem()
        {
        cout<<"Mem default , num: "<<num<<endl;
        }
        Mem(int i):num(i)
        {
        cout<<"Mem,num : "<<num<<endl;
        }
        int num = 2;
};
class Group{
        public:
        Group()
        {
        cout<<"Group default . val: "<<val<<endl;
        }
        Group(int i):val('G'),a(i)
        {
        cout<<"Goup val: "<<val<<endl;
        }
        void NumofA()
        {
        cout<< " number of A: "<<a.num<<endl;
        }
        void NumofB()
        {
        cout<<" number of B: "<<b.num<<endl;
        }
        private:
        char val{'g'};
        Mem a;
        Mem b{19};
};

int main()
{
Mem member;
Group group;
group.NumofA();
group.NumofB();
Group group2(7);
group2.NumofA();
group2.NumofB();
}

运行结果:

sizeof是一个特殊运算符,在C++11中使用sizeof操作是合法的,而在c++98里并不支持。在c++98里没有定义类实例时要获得类成员的大小可以采用如下操作:

强制转换0为一个People类的指针,继而通过指针的解引用获得其成员变量

例子:

#include <iostream>
using namespace std;

class People
{
public:
        int hand;
        static People* all;
};

int main()
{
        People p;
        cout<<sizeof(p.hand)<<endl;
        cout<<sizeof(People::all)<<endl;
        cout<<sizeof(People::hand)<<endl;
}

扩展的friend语法

friend 关键字用于声明类的友元,友元可以无视类中成员的属性。无论成员是public,protected,private

友元类或友元函数都可以访问

在C++11中,声明一个类为另外一个类的友元时,不需要再使用class关键字

在C++11中,可以为类模版声明友元

在使用类P为模版参数时,P是People<P>的一个friend类,而在使用内置int类型作为模版参数时,People<int>会被实例化为一个普通的没有友元定义的类型。

例子:

#include <iostream>
class Validator;
using namespace std;
template<typename T>
class DefenderT
{
        public:
                friend T;
                void Defence(int x,int y){}
                void Tackle(int x,int y){}
        private:
                int pos_x = 15;
                int pos_y = 0;
                int speed = 2;
                int stamina =120;
};

template<typename T>
class AttackerT
{
        public:
                friend T;
                void Move(int x,int y){}
                void SpeedUp(float ratio){}
        private:
                int pos_x = 0;
                int pos_y = -30;
                int speed = 3;
                int stamina = 100;
};

using Defender = DefenderT<int>;
using Attacker = AttackerT<int>;
using DefenderTest = DefenderT<Validator>;
using AttackerTest = AttackerT<Validator>;
class Validator
{
        public:
                void Validate(int x,int y,DefenderTest& d){}
                void Validate(int x,int y,AttackerTest& a){}
};


int main()
{
        DefenderTest d;
        AttackerTest a;
        a.Move(15,30);
        d.Defence(15,30);
        a.SpeedUp(1.5f);
        d.Defence(15,30);
        Validator v;
        v.Validate(7,0,d);
        v.Validate(1,-10,a);
        return 0;
}

猜你喜欢

转载自blog.csdn.net/ziggyPLAYguitar/article/details/82503410