C++11

<1>统一的列表初始化

C98支持对数组和结构体进行统一的{ }列表初始化设定

C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

struct Point
{
 int _x;
 int _y;
};
int main()
{
 int array1[] = { 1, 2, 3, 4, 5 };
 int arr[]{1,2,3,4,5};//c++11
 int array2[5] = { 0 };
 int arr2[5]{0};//c++11
 Point p = { 1, 2 };
 Point p{ 1, 2 };
 // C++11中列表初始化也可以适用于new表达式中
 int* pa = new int[4]{ 0 };
 return 0;
}

创建对象时也可以使用列表初始化方式调用构造函数初始化

class Date
{
    public:
    Date(int year=2020,int month=1,int day=1)
        :_year(year),_month(month),_day(day)
    {}
    private:
    int _year;
    int _month;
    int _day;
}
int main()
{
    Date d1(2023,3,3);
   C++11支持的列表初始化,这里会调用构造函数初始化
    Date d2={2023,3,3};
    Date d3{2023,3,3};
    return 0;
}

列表初始化的原理使构造临时对象,再拷贝构造,C++11把{1,2}这种类型当作initializer_list<int>类型,编译器开了一个数组把这些值存起来,initialize_list是一个类,类中有一个指针(迭代器),c++11以后所有容器都支持initizalize_list版本的构造

 调用支持 list/vector (initializer_list<value_type> il)类似这样的构造函数
    vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
    vector<int> v2 { 1, 2, 3, 4, 5, 6 };

    list<int> lt1 = { 1, 2, 3, 4, 5, 6 };
   list<int> lt2{ 1, 2, 3, 4, 5, 6 };

使用场景:

std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加 std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator= 的参数,这样就可以用大括号赋值

int main()
{
 vector<int> v = { 1,2,3,4 };
 list<int> lt = { 1,2 };
 // 这里{"sort", "排序"}会先初始化构造一个pair对象
 map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
// 使用大括号对容器赋值
v = {10, 20, 30};
 return 0;

让自己模拟实现的容器支持{}的初始化和赋值

template<class T>
class vector {
public:
     typedef T* iterator;
     vector(initializer_list<T> l)
     {
         _start = new T[l.size()];
         _finish = _start + l.size();
         _endofstorage = _start + l.size();
         iterator vit = _start;
         typename initializer_list<T>::iterator lit = l.begin();
         while (lit != l.end())
         {
             *vit++ = *lit++;
         }
         //for (auto e : l)
         //   *vit++ = e;
     }
     vector<T>& operator=(initializer_list<T> l) {
         vector<T> tmp(l);
         std::swap(_start, tmp._start);
         std::swap(_finish, tmp._finish);
         std::swap(_endofstorage, tmp._endofstorage);
         return *this;
     }
private:
     iterator _start;
     iterator _finish;
     iterator _endofstorage;
 };
}

<2>C++11中废弃auto原来的用法,将 其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初 始化值的类型。

<3>.关键字decltype将变量的类型声明为表达式指定的类型

// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}

<4>.容器变化

C++新增unorder_map和unorder_set很重要(以后更新博客),array和forward_list没什么用

<5>右值引用和移动语句

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。 什么是左值?什么是左值引用? 左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋 值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。定义时const修饰符后的左 值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。
int main()
{
// 以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;
return 0;
}

什么是右值?什么是右值引用?
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引
用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能
取地址。右值引用就是对右值的引用,给右值取别名。
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可 以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地 址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用。
int main()
{
 double x = 1.1, y = 2.2;
 int&& rr1 = 10;
 const double&& rr2 = x + y;
 rr1 = 20;
 rr2 = 5.5;  // 报错
 return 0;
}
左值引用总结: 1. 左值引用只能引用左值,不能引用右值。 2. 但是const左值引用既可引用左值,也可引用右值
右值引用总结: 1. 右值引用只能右值,不能引用左值。 2. 但是右值引用可以move以后的左值。
int main()
{
 // 右值引用只能右值,不能引用左值。
 int&& r1 = 10;
 
 // error C2440: “初始化”: 无法从“int”转换为“int &&”
 // message : 无法将左值绑定到右值引用
 int a = 10;
 int&& r2 = a;
 // 右值引用可以引用move以后的左值
 int&& r3 = std::move(a);
 return 0;
}

左值引用解决

  1. 做参数,减少拷贝,提高效率 2.做输出型参数

  1. 做返回值,减少拷贝,需要注意对象是否销毁 2.在外面可以修改返回对象

右值引用

  1. 内置类型右值,纯右值

  1. 自定义类型右值,将亡值,资源转移

C++11为push_back和构造类的接口都提供了移动构造和移动赋值

万能引用和完美转发

模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力, 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值, 我们希望能够在传递过程中保持它的左值或者右值的属性,所以需要完美转发,std::forward 完美转发在传参的过程中保留对象原生类型属性

每一层 都需要把x变成std::forward(x)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值