C++11 新特性学习笔记

7 篇文章 0 订阅
  • 变长参数实例 __VA_ARGS__ 替换省略号代表的字符串
#define LOG(...){\
	fprintf(stderr,"File: %s ,Func: %s ,Line: %d\t",__FILE__,__FUNCTION__,__LINE__);\
	fprintf(stderr,__VA_ARGS__);\
	fprintf(stderr,"\n");\
}

//Test
LOG("Msg:%s", "I am error");
  • 断言assert

断言是在运行期进行验证,适用于Debug调试使用

	assert(sizeof(int) == 8);
  • 静态断言

编译阶段就可以验证

//static_assert(sizeof(int) == 8, "This is Error!");
static_assert(sizeof(int) == 4, "64-bit code generation is not supported.");
  • #error

#error需要和ifdef 配合使用,判断某些特定条件

#ifdef _COMMPP
	std::cout << "all right!" << std::endl;
#else
//#error "this is error";
#endif
  • noexcept修饰符与noexcept操作符

    方法一,仅添加一个noexcept修饰符,在抛出异常时,调用std::terminate中断程序执行,noexcept默认为noexcept(true)
    比基于异常机制的throw()在效率上会高一些。这是因为异常机制会带来一些额外开销。

void func_no_exce() noexcept;

void class::func_no_exce() noexcept
{
	throw 1;
}


//Test
try
{
    log.func_no_exce(); //不抛异常    
}
catch (...)
{
    std::cout << "func_no_exce!\n";
}

方法二,添加一个noexcept修饰符和常量表达式(值为true,说明不会抛出异常;反之,则可能会抛出异常),在抛出异常时,调用std::terminate中断程序执行

void func_no_exce(int val) noexcept(false);
void class::func_no_exce(int val) noexcept(false)
{
	throw 1;
}
//Test
try
{
   
    log.func_no_exce(0); //抛出异常,被catch捕获
}
catch (...)
{
    std::cout << "func_no_exce!\n";
}
  • noexcept作为操作符

noexcept(expression),noexcept操作符不对expression求值。

若expression含有至少一个下列潜在求值的构造则结果为false。

    [a] 调用没有指定不抛出异常的任意类型函数,除非它是常量表达式。
    [b] throw表达式。
    [c] 目标类型是引用类型,且转换时需要运行时检查的dynamic_cast表达式。
    [d] 参数类型是多态类类型的typeid表达式。

void test() { }
void test_noexcept() noexcept(true) { }
void test_noexcept_false() noexcept(false) { }
cout << noexcept(test()) << endl;                       // false
cout << noexcept(test_noexcept()) << endl;              // true
cout << noexcept(test_noexcept_false()) << endl;        // false
cout << noexcept(throw) << endl;                        // false
  • noexcept做操作符,应用于模板

该函数是否是一个noexcept的函数取决于T()是否会抛出异常,第二个noexcept就是一个noexcept操作符,当其参数是一个有可能抛出异常的表达式的时候,其返回值为false,反之为true。

template<class T>
void fun_template()noexcept(noexcept(T())) { throw 1; }

class Base
{
public:
	void f() {}
};

class Log :public Base
{
public:
	Log() {}
	//noexcept做模板
	~Log() noexcept(false) { }
	void fun_test_template();

};

void Log::fun_test_template()
{
    cout << noexcept(Log()) << endl;
    cout << noexcept(Base1()) << endl;
    try
    {
	fun_template<Log>();
    }
    catch (...)
    {
	cout << "throw fun_template Log" << endl;    throw
    }

    try
    {
	fun_template<Base1>();   // terminate
    }
    catch (...)
    {
	cout << "throw fun_template Base1" << endl;
    }
}


class Base1 :public Base
{
public:
	~Base1()noexcept(true) { }
};

//Test
log.fun_test_template();
  • 快速初始化成员变量

“就地”声明:支持在类声明的时候使用等号"="初始化类中静态成员变量,这种声明方式我们称之为“就地”声明

C++98要求静态成员必须满足常量性,而且类型必须是整型或者枚举型,而非静态成员变量的初始化则必须在构造函数中进行。在C++11中,允许使用 等号= 或者 花括号{} 进行就地的非静态成员变量初始化。

初始化列表的效果总是优先于就地初始化。

//快速初始化成员变量
class InitVal 
{
public:
	InitVal(); 
	InitVal(int val_1, int val_2);
	InitVal(int val) :val1(val), val2(val){}
	
	~InitVal() {}
private:
	//普通成员就地初始化
	int val0 = 0;
	//普通成员变量
	int val1, val2;
	//静态成员变量
	static long val3;
	//静态常量成员
	static const long val4=0;
	//使用花括号就地初始化
	string b{ "hello" };
};
 long InitVal::val3 = 0;

 //构造函数体内初始化
 InitVal::InitVal()
 {
	 val1 = 0;
	 val2 = 0;
 }
 //构造函数初始化列表
InitVal::InitVal(int val_1, int val_2):val1(val_1), val2(val_2)
{
}
  • 友元 friend  扩展的友元

//声明一个类为另外一个类的友元时,不再需要使用class关键字
//声明友元类时,甚至可以使用类的别名。

class Car;
typedef Car BC;

class BYD
{
    friend class Car; //C98标准、C++11标准
};

class ChangAn
{
    friend Car;    //C++11标准
};

class JILi
{
    //使用别名
    friend BC;//C++11标准
};

//为类模板声明友元            //C++11标准
template <typename T>
class BenChiCar
{
    friend T;
};

BenChiCar<Car> bc;
//int的友元声明会被忽略
BenChiCar<int> bc;
     
  • 函数模板

建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板

函数模板定义

       

声明方式
        template <typename T1,typename T2....> 应用于函数头
        template <class T1,class T2....>    应用于类头
调用方式
        Func(a,b); 自动类型推导,类型要相同
        Func<T1,T2....>(a,b)显示类型调用

template <typename T>
T mySwap(T &a, T&b)
{
	cout << __FUNCTION__ << "typename" << endl;
	T t;
	t = a;
	a = b;
	b = t;
	cout << "a=" << a << ",b=" << b << endl;
	retunr t;
}

template <typename T>
void mySwap(T &a, T&b)
{
    cout << __FUNCTION__ <<"typename" << endl;
    T t;
    t = a;
    a = b;
    b = t;
    cout << "a=" << a << ",b=" << b << endl;
}

int a = 1, b = 2;
mySwap<>(a, b);//显示类型调用
mySwap<int>(a, b);//显示类型调用
cout << "a=" << a << ",b=" << b << endl;

函数模板与普通函数区别

       函数模板不允许自动类型转化;普通函数能够进行自动类型转换

       函数模板可以像普通函数一样被重载;C++编译器优先考虑普通函数;如果函数模板可以产生一个更好的匹配,那么选择模板; 可以通过空模板实参列表的语法限定编译器只通过模板匹配;

当普通函数和函数模板重载时,如果隐式调用,编译器会优先普通函数

//普通函数
void mySwap(int &a, int &b)
{
	cout << __FUNCTION__ << endl;
	int t;
	t = a;
	a = b;
	b = t;

	cout << "a="<<a<<",b="<<b << endl;
}

//函数模板
template <typename T>
void mySwap(T &a, T&b)
{
	cout << __FUNCTION__ <<"typename" << endl;
	T t;
	t = a;
	a = b;
	b = t;
	cout << "a=" << a << ",b=" << b << endl;
}


int a = 1, b = 2;
//当普通函数和函数模板重载时,如果隐式调用,编译器会优先普通函数
mySwap(a, b);  此处调用普通函数
//需要使用显示调用
mySwap<>(a, b);//显示类型调用
mySwap<int>(a, b);//显示类型调用

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值