C++11新特性(二)

目录

 

=default, = delete 配合构造函数和拷贝赋值 一起使用

Alias Template(template typedef)

Type Alias别名

using

noexcept

override

final

decltype

lambda

右值引用


=default, = delete 配合构造函数和拷贝赋值 一起使用

对于一个空的class c++编译器处理之后就会不在是一个空的class 因为编译器会为这个class添加

  1. copy ctor
  2. copy assignment operator(=)
  3. dtor

就是Big Three 如果你没有声明ctor 编译器会为你声明一个default ctor且都是public inline的

目的:是为了在这些函数中添加一些默认的行为,比如在ctor中调用父类的ctor或者dtor中调用父类的dtor

class Empty{}; ==>
class Empty{
public:
  // Big Three
  Empty() {...}
  ~Empty() {...}
  Empty(const Empty& e) {...} // 默认行为是一个位一位的拷贝
  Empty& operator-()(const Empty& e){...}
}

如果一个类中包含指针对象 就需要自己实现 Big Three

参考:https://blog.csdn.net/weixin_38339025/article/details/89161324?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

Alias Template(template typedef)

template<typename T>
using Vec = std::vector<T, MyAlloc<T>>;//给一个化名
Vec<int> coll;
 
//typedef 做不到,typedef不能接受参数
//define 也不行
//#define Vec<T> template<typename T> std::vector<T,MyAlloc<T>>;
//Vec<int> coll;

Type Alias别名

// typedef void(*func)(int, int);
// func是一个类型 是一个函数指针
// 和typedef没有区别
using func = void(*)(int, int);

void example(int, int) {};
// 函数名就是一个函数指针
func fn = example;

using

一般的using关键子我们都是用来声明当前文件的命名空间,比如标准库的命名空间std-> using namespace std;

但在c++11中,它的用处还有几个 1:取代typedef  ,2:让父类同名函数在子类中以重载方式使用.

// #1 using namespace std; using std::count;
// #2 声明成员函数 Base::test
// #3 用于alias

noexcept

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

void foo() noexcept;
void foo() noexcept(true); // 表明在上面条件下不会丢异常

override

在成员函数声明或定义中, override 确保该函数为虚函数并覆写来自基类的虚函数。
位置:函数调用运算符之后,函数体或纯虚函数标识 “= 0” 之前。

注意在派生类的成员函数中使用override时,如果基类中无此函数,或基类中的函数并不是虚函数,编译器会给出相关错误信息。

final

1、禁用继承:C++11中允许将类标记为final,方法时直接在类名称后面使用关键字final,如此,意味着继承该类会导致编译错误。

实例如下:

class Super final
{
  //......
};

2、禁用重写: C++中还允许将方法标记为fianal,这意味着无法再子类中重写该方法。这时final关键字至于方法参数列表后面,如下

class Super
{
  public:
    Supe();
    virtual void SomeMethod() final;
};

decltype

这个关键字的功能类似 typeof 返回对象的类型。它的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

总结:decltype和auto都可以用来推断类型,但是二者有几处明显的差异:1.auto忽略顶层const,decltype保留顶层const;2.对引用操作,auto推断出原有类型,decltype推断出引用;3.对解引用操作,auto推断出原有类型,decltype推断出引用;4.auto推断时会实际执行,decltype不会执行,只做分析。总之在使用中过程中和const、引用和指针结合时需要特别小心。

template<typename T1, typename T2>
auto add(T1 x, T2 y) -> decltype(x+y);

// error 因为编译到decltype(x+y)的时候 编译器不知道xy是什么东西
template<typename T1, typename T2>
decltype(x+y) add(T1 x, T2 y);
// auto cmp由编译器推导出类型
auto cmp = [](const Person& p1, const Person& p2) {
  	return p1.lastname() > p2.lastname();
}
// set需要传递一个函数类型 用decltype可以得出
std::set<Person, decltype(cmp)> coll(cmp);

参考:cnblogs.com/cauchy007/p/4966485.html

lambda

lambda没有构造和赋值函数。利用Lambda表达式,可以方便的定义和创建匿名函数。

auto l = [] {
	strd::cout << "hello lambda" << std::endl;
}
l();

[...]中传递外部的变量
[&]传引用 mutable表示放在[]里面的变量可变 > > [=]表示默认接收外界的所有变量

右值引用

右值引用是新型的引用类型 帮助避免不必要的复制

当赋值的右手边是一个右值的时候 左手边的接受端可以偷右手边的资源而不需要执行allocation动作

Lvalue 可以出现在 = 左边 (左值表示变量的地址)

Rvalue 只能出现在 = 右边 (右值表示存储的真实的值)

类的临时对象是一个右值,临时变量一定被当成右值,因为临时对象创建之后 不会再被使用 所以直接把右值数据引用给别的变量,有时候一个左值在后面不会被用到,那么就可以使用move语义 把左值转成右值。

右值引用我的理解是编译器提供了一个接口 允许你进行赋值的时候直接使用右值的内存空间(其实就是将指针指向这块空间,当然在进行copy ctor和copy asgn的时候你需要自己实现操作,因为当你实现了右值引用的机制后编译器会自动调用你实现的函数),对于一些左值 但是如果在接下来的scope中你用不到了 在进行赋值的时候可以使用move语句将左值转变为右值,因为左值后面用不到了所以你可以把左值指向的内存的指针给删除(注意一定要删除指针,因为当这个左值的scope结束后,编译器会调用析构函数,如果没有删除指针,会把你move出去的这块内存给删除所以就造成了错误)

参考:https://www.zhihu.com/question/22111546/answer/30801982

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值