【C++碎碎念】C++11新特性(声明、智能指针、右值引用、lambda表达式)

2023-11-09

目录

一、新类型

二、统一的初始化

三、声明

四、智能指针

五、右值引用

六、Lambda表达式


一、新类型

C++11新增了long long和unsigned long long,以支持64位(或更宽)的整型,新增了类型char16_t 和 char32_t ,以支持16位和32位的字符表示;还新增了“原始”字符串。

cout<<"C:\\Program Files (x86)\\Dell Digital Delivery Services"<<endl;

\\必须是双斜杠,否则会报错

二、统一的初始化

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

int x={9};

double y={2.25};

vector<int> v{1,2,3,4}; 

class person{

 public:

        string name;

        int age;

        person(string n,int g):name(n),age(g);

};

person s1("xz",18);

三、声明

1、auto

实现自动类型转换,要求显示初始化,让编译器能够将变量的类型设置为初始值的类型:

auto   a = 12; //自动将a转换成int类型;

auto   ptr = &a;  //自动将ptr转换成int *类型,将a的地址赋给ptr;

2、decltype

decltype将变量的类型声明为表达式指定的类型。

decltype(表达式)var;//让var的类型与表达式的类型相同

比如:

int a=10;

decltype(a)b;//  因为a的类型是int,所以b的类型也是int.

double x;

int y;

decltype(x*y) q;//x*y为double型,所以q也为double型

decltype(&x) ab;//&x为double*类型,所以ab也为double*类型

注意:为了确定类型,编译器必须遍历一个核对表

第一步:如果 表达式 是一个没有用括号括起来的标识符,则var的类型与该标识符的类型相同,包括const等限定符;

double &rx=x;

const double * pd;

decltype(rx) u = y;//因为rx是double &类型,所以u也为double &类型

decltype(pd) v; //因为pd为const double *类型,所以v也为const double *类型。

第二步:如果表达式是一个函数调用,则var的类型与函数的返回类型相同

第三步:如果表达式是一个左值,则var为指向其类型的引用。要进入这一步,表达式不能是未用括号括起来的标识符。

double xx=4.4;

decltype((xx)) r2 =xx;//double &;

decltype(xx) w = xx ;//double类型

第四步:如果前面的条件都不满足,则var的类型与表达式的类型相同

int j=3;

int &k=j;

int &n=j;

decltype(j+6) i;//int型

decltype(k+n) x;// int型

decltype((k+n)) //int &型

四、智能指针

如果在程序中使用new从堆(自由存储区)分配内存,等到不需要时,应使用delete将其释放。

C++引入了智能指针auto_ptr,以帮助自动完成这个过程,智能指针是行为类似于指针的类对象。

在使用时(尤其是STL),需要更精致的机制,C++摒弃了auto_ptr,并新增了三种智能指针:

unique_ptr、share_ptr和weak_ptr。

举个例子:

格式:auto_ptr<类型> 变量名(new 类型)

如:auto_ptr<int> num(new int);

#include <memory>
void demo1(){
    double *pd=new double;//普通开辟了一段内存,但是后续没有释放内存,这样会很危险
    *pd=28.9;
} 
//使用智能指针就可以不用考虑这个问题
void demo2(){
    auto_ptr<double> ap(new double);//使用智能指针,即使后续不delete,他也会自己释放内存
    *ap=26.56;
}

由于智能指针模板类的定义方式,智能指针对象的很多方面都类似于常规指针。例如,如果num是一个智能指针对象,则可以对他执行解除引用操作(*num)、用它来访问结构成员(num->m_name)、将他赋给指向相同类型的常规指针。还可以将智能指针对象赋给另一个同类型的智能指针对象。

比如:

auto_ptr<string> ps(new string("abc"));
auto_ptr<string> ab;
ab=ps;//

如果ps和ab都是常规指针,则两个指针指向同一个string对象,这样ps和ab过期时会释放一块内存两次,避免这种问题,有以下几种方式:

1、重载赋值运算符,使之执行深拷贝,这样两个指针指向不同的对象,其中一个对象是另外一个对象的副本;

2、建立所有权概念,对于特定的对象,只能有一个智能指针可拥有它,这样只有拥有对象的智能指针的析构函数会释放该对象。然后,让赋值操作转让所有权,这就是用于auto_ptr和unique_ptr的策略,但unique_ptr的策略更严格;

3、创建智能更高的指针,跟踪引用特定对象的智能指针计数。这就称为引用计数。例如,赋值时,计数将加1,而指针过期时,计数将减1.只有当最后一个指针国企时才会调用delete,这就是shared_ptr采用的策略。

同样的策略也适用于赋值构造函数。

不适用于auto_ptr的实例,因为编译时不会报错,但是执行的时候会报错。

auto_ptr<string> ps(new string("abc"));
auto_ptr<string> vo;
vo=ps;
cout<<*ps<<endl;//当把ps赋给vo时,就相当于把ps的所有权转让给vo了,所以此时解引用读取ps里的值会报错

但是可以使用shared_ptr代替auto_ptr,毕竟shared是共享的意思嘛,所以这是没问题的。

shared_ptr<string> ps(new string("def"));
shared_ptr<string> pd;
pd=ps;
cout<<*ps<<endl;

使用unique_ptr代替auto_ptr。

unique_ptr<string> ps(new string("abc"));
unique_ptr<string> pd;
pd=ps;
cout<<*ps<<endl;

这样也会报错,但是跟auto_ptr的区别就是unique_ptr编译时就会报错.

这么多的智能指针,我到底改选哪一个呢?

如果程序要使用多个指向同一个对象的指针,应该选用shared_ptr;

如果程序不需要多个指向同一个对象的指针,则可以使用unique_ptr;

如果使用new[]分配内存,应该选用unique_ptr;

如果函数使用new分配内存,并返回指向该内存的指针,将其返回类型声明为unique_ptr是不错的选择。

五、右值引用

右值引用就是必须绑定到右值的引用。我们通过&&而不是&来获得右值,右值引用有一个重要的特性-只能绑定到一个将要销毁的对象。

关于左值引用/右值引用的几点说明

1、左值表示一个对象的身份,右值表示对象的值;

int i=42;

int &r=i; //r引用i,这表示左值引用

int &&rr=42;//将rr与42绑定在一起,这是右值引用

int &&aa=i*2;//将aa与表达式i*2绑定在一起。

int &&bb=x+y;//都是临时的数值,用完就释放了

上式相当于把x+y的结果赋给临时变量temp,然后将这个临时变量temp赋给bb这个变量

2、左值引用:&,绑定到左值表达式中,如变量,函数,赋值,下标,解引用,前置递增/递减运算符;

3、右值引用:&&,绑定到字面常量,要求转换到表达式,右值表达式等;

4、左值代表的资源是持久的,右值代表的资源是短暂的;

5、const左值引用:因为是const,无法修改资源,因此绑定到暂时性资源上,也就是绑定到右值引用上;

6、变量是左值,右值引用的本质是变量,所以无法将右值引用绑定到另一个右值引用上。

六、Lambda表达式

lambda表达式又叫匿名函数,简单的理解为没有名称的函数。

lambda表达式很简单那,可以套用如下的语法格式:

[外部变量访问方式说明符](参数)mutable noexcept/throw() -> 返回值类型

{

        函数体;

}

解释:

1、[外部变量方位方式说明符]

[ ] 方括号用于向编译器表明当前是一个lambda表达式,其不能被省略。在方括号内部,可以注明当前lambda函数的函数体中可以使用哪些“外部变量”。

所谓外部变量,指的是和当前lambda表达式位于同一作用域内的所有局部变量。

这个方括号也叫捕获块,主要的类型有以下几种(用的比较多)

[ ] 默认不捕获任何变量;

[=]默认以复制捕获所有变量;

[&]默认以引用捕获所有变量;

[x]仅以复制捕获x,其他变量不捕获;

2、(参数)

和普通函数的定义一样,lambda匿名函数可以接受外部传递的多个参数,和普通函数不同的是如果不需要传递参数则连同()一起省略。

3、mutable

此关键字可以省略,如果要使用的话之前的()就不能省略,默认情况下,对于以值传递引入的外部变量,不允许在lambda表达式内部修改他们的值(比如const常量)。如果想要修改他们,就必须使用mutable关键字。

注意:对于以值传递方式引入的外部变量,lambda表达式修改的是拷贝的那一份,并不会修改外部的值。

int x=10;

auto lam=[x](int a)->int

{

        x++;

        return a+x;

}

cout<<lam(10)<<endl;//21 ,因为x自增1,变为11,11+10=21

cout<<x<<endl; //10,值传递只修改拷贝的那一份,外部不改变值得大小。

4、noexcept/throw()

可以省略,如果使用,在之前的小括号将不能省略,默认情况下lambda函数的函数体可以抛出任何类型的异常,而标注noexcept则不会出现任何的异常。

5、->返回值类型

指明lambda匿名函数的返回值类型,非常智能的是,如果lambda函数体内只有一个return语句,或者该函数返回void,则编译器会自动的识别出返回值类型。

int num[4]={3,2,4,1};

sort(num,num+4,[](int a,int b){return a>b};);//这样会自动识别出返回类型是bool类型。

6、函数体

和普通函数一样,lambda匿名函数包含的内部代码都放置在函数体内,该函数体内除了可以使用指定传递进来的参数外,还可以使用指定的外部变量以及全局范围内的所有全局变量。

具体函数为:

lambda.cpp

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int num[4]={9,8,4,5};
    sort(num,num+4,[=](int a,int b)->bool
    {
        return a>b;//按照从大到小排序
    }
 );
    for(auto a:num)
    cout<<a<<" ";//9 8 5 4
    cout<<endl;
    return 0;
}

使用Linux编译时,使用命令:g++ -std=c++11 lambda.cpp -o lambda,这样编译才不会出错。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++碎碎念】C++11新特性(声明、智能指针、右值引用、lambda表达式) 的相关文章

  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • DrawerLayout的openDrawer()和closeDrawer()方法

    如下代码 DrawerLayout mdrawerLayout Button btn 以上为声明组件 为简便其余过程省略 btn setOnClickListener new OnClickListener mdrawerLayout op
  • Go Web编程实战(8)----创建HTTP与HTTPS服务器端

    目录 创建一个HTTP服务端 ListenAndServe ServeHTTP 方法的使用示例 定义Refer结构体 实现ServeHTTP 方法 创建一个HTTPS服务端 创建证书与私钥 创建HTTPS服务端 创建一个HTTP服务端 其实
  • 2021-07-16

    VUE 生命周期 vm的一生 将要创建 gt 调用beforeCreate函数 创建完毕 gt 调用create函数 将要挂载 gt 调用beforeMount函数 挂在完毕 gt 调用mounted函数 将要更新 gt 调用beforeU
  • 计算机打字盲打方法,练习键盘打字方法 盲打的指法练习

    1 牢记键盘字母的排序 键要是字母键构成 二十六个字母排成了三排 因此手指要会上下灵活伸缩 最长的键是空格键 带一个横箭头标着Enter的是回车键 回车往往有确定 换行 打开的意思 2 打字的时候手势要正确 先把二十六个字母背下来 就像背古
  • docker创建vue编译环境

    docker创建vue编译环境 node的docker获取 docker pull node latest 升级node npm install g npm 8 9 0 to update 安装vue环境 npm config set re
  • cmd命令查找文本文件中的字符串

    cmd命令查找文本文件中的字符串 可以通过findstr命令实现查找文本文件当中的字符串 这样方便提高日志的检索交率 如下图 命令格式 findstr s n aaa C Users 17676 Desktop 667 txt s 在当前目
  • 亲密关系沟通-【信任感】-巩固信任感的沟通方法

    案例 老公答应做家务 同意了 但是总觉得他会忘 提醒他 结果嫌我啰嗦 我们还大吵一架 我真的是一个不会信任对方的人吗 要有信任感 你需要在沟通中成为两个人 1 能让别人信任你的人 2 有能力信任别人的人 其实你不信任ta 不是ta的原因 而
  • APP兼容性测试需要注意哪几点?-alltesting云测试

    由于终端设备的型号多样 机型的碎片化 使得APP兼容性问题在APP测试中成为一个不得不考虑的问题 因为一旦APP有兼容性方面的问题 就会影响这一类的很多用户 对业务的影响会比较大 针对这个问题的测试需要考虑覆盖多种不同的场景 严格来说 兼容
  • 【HDLbits刷题笔记 】04-verilog语法-程序部分

    Always块 组合 由于数字电路由用导线连接的逻辑门组成 因此任何电路都可以表示为模块和分配语句的某种组合 但是 有时这不是描述电路的最方便方法 过程 始终以块为例 提供了描述电路的替代语法 对于合成硬件 synthesizing har
  • Android adb等 获取root权限

    Android adb 获取root权限 1 自己编译的Android 中 adb shell后 自动获取root权限 即显示 而不是 方法 修改 default prop 把ro secure设为0 persist service adb
  • 位段的跨平台问题

    笔者在之前的两篇文章中已经详细的详解了 位段的各种问题 有意者请参考一下 位段的基础知识 大家都不怎么知道位段 参考链接为 位段的基础知识 大家都不怎么知道位段 念君思宁的博客 CSDN博客 对于位段的概念 想必大多数的C语言学者 都是不知
  • 接口接收数据_RGMII接口布线经验

    网络设备一定离不开MAC和PHY 有MAC和PHY的地方就有相应的接口 无论看得见或者看不见 它就在那里 不悲不喜 在以太网中 这个接口就是介质无关接口 英文称为Media Independent Interface 简称MII MII适用
  • 部署rancher

    rancher部署kubernetes 节点提前安装好docker环境 部署rancher 根据官网选择合适的rancher版本 并配置数据持久化启动rancher docker run d name rancher restart unl
  • QObject成员函数connect()函数

    1 首先要链接的两个类必须继承于QObject 同时添加 Q OBJECT 2 在qt中QObject connect中填写的signal和slot函数 一定要填写参数类型 因为类中的函数可以 也就是 重载函数名一样 参数不一样 如果QOb
  • C语言基础入门48篇_20_函数入门:为什么使用函数?(函数使得程序模块化 使用函数封装细节,使得程序员只要面向函数的接口编程(参数与返回值),而不用关心函数内部细节)

    菜鸟和高手都会基本 那菜鸟为什么是菜鸟 高手为什么是高手呢 很大的区别在于 高手写的程序 结构性 更好 更容易维护 而函数就是C语言结构化的一种手段 函数可以将大的计算任务划分为多个较小的任务 解耦合 一个设计得当的函数可以将不必要的细节给
  • 【C++]】蓝桥杯练习题 (入门训练 Fibonacci数列)

    img src data image png base64 iVBORw0KGgoAAAANSUhEUgAAA60AAAG8CAYAAAA1sEPIAAAgAElEQVR4Aey9TYudVdb v2x8Awa56QYRRTAgOPBHpS
  • 把eclipse的web项目导入到idea中

    一 导入项目 1 导入 2 module选择eclipse 没有该步骤可以跳过 3 之后一路next即可 二 配置依赖 1 配置依赖和jar包 1 Project 选择相应的sdk 2 Modules 选择导入的模块dataweb 选择De
  • SpringBoot快速实践 --Ⅰ

    文章目录 启动一个SpringBoot项目 如何替换内嵌容器 玩转SpringBoot配置 全局异常处理 过滤器 拦截器 使用Lombok简洁代码 使用IDEA HTTP Client进行接口调试 启动一个SpringBoot项目 如果你觉
  • house of storm

    一 漏洞利用条件 house of storm是一种结合了unsorted bin attack和large bin attack的攻击技术 其基本原理和large bin attack类似 漏洞发生在unsorted bin的chunk放
  • 【C++碎碎念】C++11新特性(声明、智能指针、右值引用、lambda表达式)

    目录 一 新类型 二 统一的初始化 三 声明 四 智能指针 五 右值引用 六 Lambda表达式 一 新类型 C 11新增了long long和unsigned long long 以支持64位 或更宽 的整型 新增了类型char16 t