C/C++教程

C++11中的新特性

本文主要是介绍C++11中的新特性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!


C++11中的新特性

文章目录



一、基于范围的for循环

C++ 11提供了一个特殊版本的 for 循环,在很多情况下,它都可以简化数组的处理,这就是基于范围的 for 循环。

在使用基于范围的 for 循环处理数组时,该循环可以自动为数组中的每个元素迭代一次。不必使用计数器变量控制其迭代,也不必担心数组下标越界的问题。
基于范围的 for 循环使用了一个称为范围变量的内置变量。每次基于范围的 for 循环迭代时,它都会复制下一个数组元素到范围变量。例如,第一次循环迭代,范围变量将包含元素 0 的值;第二次循环迭代,范围变量将包含元素 1 的值,以此类推

基于范围的for循环的一般格式
 

for (dataType rangeVariable : array)    //可以结合auto一起使用
       statement;

dataType:是范围变量的数据类型。它必须与数组元素的数据类型一样,或者是数组元素可以自动转换过来的类型。(可以使用auto)
rangeVariable:是范围变量的名称。该变量将在循环迭代期间接收不同数组元素的值。在第一次循环迭代期间,它接收的是第一个元素的值;在第二次循环迭代期间,它接收的是第二个元素的值;以此类推。
array:是要让该循环进行处理的数组的名称。该循环将对数组中的每个元素迭代一次。
statement:是在每次循环迭代期间要执行的语句。要在循环中执行更多的语句,则可以使用一组大括号来包围多个语句。
举例子
例如,假设已经定义了以下数组:
int numbers[] = {1,3,5,7,9,2,4,6,8,10};
可以使用基于范围的 for 循环来显示 numbers 数组的内容。语句如下

for(int val : numbers)
{
    cout << "The next value is ";
    cout << val << endl;
}


当然了,也可以使用auto关键字,代码如下

for (auto val : numbers)
{
    cout << "The next value is ";
    cout << val << endl;
}

使用基于范围的 for 循环来修改数组

当基于范围的 for 循环执行时,其范围变量将仅包含一个数组元素的副本。因此,不能使用基于范围的 for 循环来修改数组的内容,除非将范围变量声明为一个引用。

要将范围变量声明为引用变量,可以在循环头的范围变量名称前面添加一个 & 符号。

#include <iostream>
using namespace std;
int main ()
{
    const int SIZE = 5;
    int numbers[SIZE];
    //Get values for the array.
    for (int &val : numbers)
    {
        cout << "Enter an integer value: ";
        cin >> val;
    }
    // Display the values in the array.
    cout << "\nHere are the values you entered: \n";
    for (int val : numbers)
    {
        cout << val << " ";
    }
    cout << endl;
    return 0;
}

请注意范围变量 val,在它的名称前面有一个 & 符号,这表示它被声明为引用变量。当循环执行时,val 变量将不再只是数组元素的副本,而是变成了元素本身的别名。因此,对 val 变量作出的任何修改都会实际作用于它当前引用的数组元素。

注意

范围for的使用条件:for循环迭代的范围必须是确定的

二、C++11完美转发

C++11完美转发及实现方法详解 (biancheng.net)

聊聊C++中的完美转发 - 知乎 (zhihu.com)

什么是C++右值?

值得一提的是,左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。很多人认为它们分别是"left value"、"right value" 的缩写,其实不然。lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 "read value",指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。

  •  赋值号(=)左侧的表达式为左值,右侧为右值
  • 有名称的、可以获取到存储地址的表达式即为左值;反之则是右值。

C++右值引用

在C++98/03中&表示引用,但只允许左值建立引用

C++11中采用 && 表示右值引用

int i=42;
int &r=i;   //正确,r引用i
int &&rr=i   //错误,不能将一个右值引用绑定到一个左值上
int &r2=i*42;  //错误,i*42是一个右值
const int &r3=i*42;  //正确,我们可以将一个const的引用绑定到一个右值上
int &&r2=i*42; //正确,将rr2绑定到乘法结果上

由于右值引用只能绑定到临时对象,我们得知
1.所引用的对象将要被销毁
2.该对象没有其他用户

 不能将一个右值引用直接绑定到一个左值上,但是可以显示地将一个左值转换为对应的右值引用类型

int &&rr3 =std::move(rr1);  //rr1为左值
//调用一个名为move的新标准库函数来获得绑定到左值上的右值引用,此函数定义在头文件utility中。

 完美转发 

std::forward  作用是保持原来的值属性不变。

通俗来讲就是:如果原来的值是左值,经std::forward处理后该值还是左值,如果原来的值是右值,经std::forward处理后它还是右值。

代码实例:

#include <iostream>

template<typename T>
void print(T & t){
    std::cout << "左值" << std::endl;
}

template<typename T>
void print(T && t){
    std::cout << "右值" << std::endl;
}

template<typename T>
void testForward(T && v){
    print(v);
    print(std::forward<T>(v));
    print(std::move(v));
}

int main(int argc, char * argv[])
{
    testForward(1);

    std::cout << "======================" << std::endl;

    int x = 1;
    testFoward(x);
}

执行结果:

左值
右值
右值
=========================
左值
左值
右值

//第一组传入的1为右值,但经过函数传参之后它变成了左值(在内存中分配了空间)
//第二行使用了std::forward函数,不会改变它的右值属性
//第三行使用了std::move函数会将传入的参数强制转成右值。

//第二组传入x变量为左值,传参过后也一定是左值
//第二行使用std::forward函数,依然保持左值
//第三行使用std::move函数,强制转换成右值



三、lambda表达式

C++ 11 中的 Lambda 表达式用于定义并创建匿名的函数对象,以简化编程工作。
Lambda 的语法形式如下:

[capture list] (params list) mutable exception-> return type { function body }

各项具体含义如下

  1. capture list:捕获外部变量列表
  2. params list:形参列表
  3. mutable指示符:用来说用是否可以修改捕获的变量
  4. exception:异常设定
  5. return type:返回类型
  6. function body:函数体
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool cmp(int a, int b)
{
    return  a < b;
}

int main()
{
    vector<int> myvec{ 3, 2, 5, 7, 3, 2 };
    vector<int> lbvec(myvec);

    sort(myvec.begin(), myvec.end(), cmp); // 旧式做法
    cout << "predicate function:" << endl;
    for (int it : myvec)
        cout << it << ' ';
    cout << endl;

    sort(lbvec.begin(), lbvec.end(), [](int a, int b) -> bool { return a < b; });   // Lambda表达式
    cout << "lambda expression:" << endl;
    for (int it : lbvec)
        cout << it << ' ';
}

 C++ 11 Lambda表达式 - 滴水瓦 - 博客园C++11的一大亮点就是引入了Lambda表达式。利用Lambda表达式,可以方便的定义和创建匿名函数。对于C++这门语言来说来说,“Lambda表达式”或“匿名函数”这些概念听起来好像很深奥,但很多https://www.cnblogs.com/DswCnblog/p/5629165.html

C++之Lambda表达式 - 季末的天堂 - 博客园1. 概述 C++ 11 中的 Lambda 表达式用于定义并创建匿名的函数对象,以简化编程工作。 Lambda 的语法形式如下: 可以看到,Lambda 主要分为五个部分:[函数对象参数]、(操作符https://www.cnblogs.com/jimodetiantang/p/9016826.html 


四、智能指针

智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源

 智能指针的作用:智能指针可以帮助我们避免在申请空间后忘记释放造成内存泄漏的问题;

shared_ptr     引用计数型智能指针

引用计数顾名思义就是在内存中记录有多少个智能指针被引用,新增一个引用计数加一,过期引用计数则减一,当引用计数为0的时候,智能指针才会释放资源;

看完这篇,别再说不会智能指针了

这篇关于C++11中的新特性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!