C++2.0—— =default,=delete、using、noexcept的介绍

=default

在C++中,当我们设计与编写一个类时,若不显著申明,则类会默认为我们提供如下几个函数:

  • 构造函数
  • 析构函数
  • 拷贝构造函数
  • 拷贝赋值函数
  • 移动构造函数(C++2.0)
  • 移动赋值函数  (C++2.0)

C++11允许添加“=default”说明符到函数声明的末尾,以将该函数声明为显示默认构造函数;这就使得编译器为显示默认函数生成了默认实现,它比手动编程函数更加有效;当我们声明一个有参构造函数时,编译器就不会创建默认构造函数。在这种情况下,我们可以使用default说明符来创建默认构造函数。

#include <iostream>

using namespace std;

class A 
{
public:
	A(int) 
	{
		cout << "A::A(int)" << endl;
	}

	//当我们定义了有参构造函数,编译器就不会生成默认的构造函数了,
	//通过=default来将该函数声明为默认构造函数
	A() = default;

};


int main() 
{
	A a;//使用默认构造函数

	A a1(10);//使用有参构造函数


	return 0;
}

=delete

在C ++ 11之前,操作符delete 只有一个目的,即释放已动态分配的内存。而C ++ 11标准引入了此操作符的另一种用法:禁用成员函数的使用,这是通过附加= delete来完成的; 说明符到该函数声明的结尾;使用’= delete’说明符禁用其使用的任何成员函数称为expicitly deleted函数,引进这种新特性的目的是为了增强对“类默认函数的控制”,从而让程序员更加精准地去控制默认版本的函数。

/********************************************************
*
* C++ 2.0之前
*
*********************************************************/
class UnCopyable {
protected:
	UnCopyable() {}
	~UnCopyable() {}
private:
	UnCopyable(const UnCopyable&);
	UnCopyable& operator=(const UnCopyable&);
};

class B : private UnCopyable 
{
	//class 不在声明copy构造函数和拷贝赋值
};

/********************************************************
*
* C++ 2.0
*
*********************************************************/

class C 
{
public:
	C(){}
	~C() {}

	C(const C&) = delete;
	C& operator=(const C&) = delete;
};


int main() 
{
	B b1, b2;
	//b1 = b2;//error C2280: “B &B::operator =(const B &)”: 尝试引用已删除的函数
	//B b3(b1);//error C2280: “B::B(const B &)”: 尝试引用已删除的函数

	C c,c1;
	//c = c1;//error C2280: “C &C::operator =(const C &)”: 尝试引用已删除的函数
	//C c2(c);//error C2280: “C::C(const C &)”: 尝试引用已删除的函数

	return 0;
}

using

1. Alias Template的使用

/*
Alias Template:
    设计一个模板,并且对这个模板的类型进行typedef操作

typedef的话因为不能传递参数T

#define只能实现字符串的替换,并不能达到目的
*/
template<typename T>
using Vec = vector<T, allocator<T>>;

2. 函数指针的定义

//给函数指针做定义,这个也是可以代替typedef的
using func = void(*)();
typedef void(*pFunc)();
 

3. 在子类中引入基类的成员,并影响访问权限

/*
1、public继承不改变基类成员的访问权限

2、private继承使得基类所有成员在子类中的访问权限变为private

3、protected继承将基类中public成员变为子类的protected成员,其它成员的访问 权限不变。

4、基类中的private成员不受继承方式的影响,子类永远无权访问。
*/
class Base {
public:
	Base() { cout << "Base::Base()" << endl; }
	
	int m_value;
	int add(int x, int y) { 
		m_value = x + y;
		return m_value; 
	}
	
};

/*
//如果在Derived中不添加using Base::add;Derived将无法访问add成员函数
*/
class Derived :private Base {

public:
	using Base::add;
	int interface(int x, int y) 
	{ 
		cout << m_value << endl;
	}
};


int main() 
{

	Derived d;
	d.add(1,2);//如果在Derived中不添加using Base::add;Derived将无法访问add成员函数
	

	return 0;
}

noexcept

从C++11开始,我们能看到很多代码当中都有关键字noexcept。比如下面就是std::initializer_list的默认构造函数,其中使用了noexcept:

      constexpr initializer_list() noexcept
      : _M_array(0), _M_len(0) { }

该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化,如果在运行时,noexecpt函数向外抛出异常(如果函数内部捕捉了异常并完成处理,这种情况不算抛出异常),程序会直接终止,调用std::terminate()函数,该函数内部会调用std::abort()终止程序。

使用noexcept表明函数或操作不会发生异常,会给编译器更大的优化空间,以下情形可以使用noexcept:

  • 移动构造函数(move constructor)
  • 移动分配函数(move assignment)
  • 析构函数(destructor)。这里提一句,在新版本的编译器中,析构函数是默认加上关键字noexcept的。下面代码可以检测编译器是否给析构函数加上关键字noexcept。
void swap(Type& x, Type& y) throw()   //C++11之前
{
    x.swap(y);
}
void swap(Type& x, Type& y) noexcept  //C++11
{
    x.swap(y);
}

/*
有条件的限制noexcept:
    如果操作x.swap(y)不发生异常,那么函数swap(Type& x, Type& y)一定不发生异常
*/

 void swap(Type& x, Type& y) noexcept(noexcept(x.swap(y)))    //C++11
 {
    x.swap(y);
 }

 

以上参考:

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值