C++11新特性

目录

  • 一、自动类型推导
    • 1、auto
    • 2、decltype(declare type 声明类型)
  • 二、左值右值
  • 三、模板的改进
  • other奇葩小知识

在学习C++11前,请确定编辑器打开了C11标准!

int main(){cout<<__cplusplus<<endl;//输出201103而不是别的return 0;
}

头文件的改变

#include<cstdio> //新的头文件为
#include<stdio.h>//兼容旧的写法

新引入的nullptr

在c++中如果表示空指针语义时建议使用nullptr而不要使用NULL,因为NULL本质上是个int型的0,其实不是个指针。

一、自动类型推导

1、auto

auto:在编译时期进行通过 = 右边的类型推导出变量类型。

// 10是int型,可以自动推导出a是int,使用 auto 类型推导的变量必须马上初始化,因为 auto 在 C++11 中只是“占位符”,并非如 int 一样的真正的类型声明。
auto a = 10; // &a 的结果是一个 int* 类型的指针,所以推导出变量 b 的类型是 int*
auto b = &a; // 双引号""围起的字符串是 const char* 类型,所以推导出变量 url 的类型是 const char*,即常量指针
auto url = "http://c.biancheng.net/cplus/";// 当 = 右边的表达式是一个引用类型时,auto 会把引用抛弃,直接推导出它的原始类型。
auto &c1  = a;   	//c1 为 int&,auto 推导为 int
auto c2 = c1;    	//c2 为  int,auto 推导为 int//  auto 与 const 结合使用时,当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性;
const auto d = a;   // d是const int
auto e = d; 		// e是int
//  auto 与 const 结合使用时,当类型为引用时,auto 的推导结果将保留表达式的 const 属性。
const auto& f = a;  // f是const int&
auto &g = f; 		// g是const int&

auto的一些使用限制规则

auto d = 0, f = 1.0; 	 // error,0和1.0类型不同,对于编译器有二义性,没法推导
auto e; 				 // error,使用auto必须马上初始化,否则无法推导类型
auto c[10] = a; 		 // error,auto不能定义数组,可以定义指针
vector<auto> f = d;      // error,auto无法推导出模板参数void func(auto value) {} // error,auto不能用作函数参数class A {auto a = 1; 		 // error,在类中auto不能用作非静态成员变量
};

auto的使用场景

// 一、简化迭代器的定义
vector< vector<int> > v;
vector< vector<int> >::iterator i = v.begin();
auto i = v.begin();  //auto 可以根据begin() 函数的返回值类型来推导出变量 i 的类型// 二、泛型编程,用于不知道变量类型,不希望指明具体类型的时候
#include <iostream>
using namespace std;class A{
public:static int get(void){return 100;}
};class B{
public:static const char* get(void){return "http://c.biancheng.net/cplus/";}
};template <typename T>
void func(void){auto val = T::get();cout << val << endl;
}int main(void){func<A>();func<B>();return 0;
}

2、decltype(declare type 声明类型)

decltype:在编译时期根据表达式类型推导出变量类型

auto 并不适用于所有的自动类型推导场景,在某些特殊情况下 auto 用起来非常不方便,甚至压根无法使用,所以 decltype 关键字也被引入到 C++11 中。

decltype推导的规则

  1. 如果 exp 是一个不被括号( )包围的表达式,或者是一个类成员访问表达式,或者是一个单独的变量,那么 decltype(exp) 的类型就和 exp 一致,这是最普遍最常见的情况。
// b是const int&,auto 要求变量必须初始化,而 decltype 不要求。
int i = 1;
decltype(i) b; //b被推导为int类型
  1. 如果 exp 是函数调用,那么 decltype(exp) 的类型就和函数返回值的类型一致。
decltype(exp) ;
// exp 这个普通的表达式可以是任意复杂的形式,但是必须要保证 exp 的结果是有类型的,不能是 void;
//例如,当 exp 调用一个返回值类型为 void 的函数时,exp 的结果也是 void 类型,此时就会导致编译错误。
decltype(10.8) x = 5.5;  //x 被推导成了 double
decltype(x + 100) y;  //y 被推导成了 double//函数声明
int& func_int_r(int, char);  //返回值为 int&
int&& func_int_rr(void);  //返回值为 int&&
int func_int(double);  //返回值为 int
const int& fun_cint_r(int, int, int);  //返回值为 const int&
const int&& func_cint_rr(void);  //返回值为 const int&&//decltype类型推导,这里 exp 中调用函数时需要带上括号和参数,但这仅仅是形式,并不会真的去执行函数代码。
int n = 100;
decltype(func_int_r(100, 'A')) a = n;  //a 的类型为 int&
decltype(func_int_rr()) b = 0;  //b 的类型为 int&&
decltype(func_int(10.5)) c = 0;   //c 的类型为 int
decltype(fun_cint_r(1,2,3))  x = n;    //x 的类型为 const int &
decltype(func_cint_rr()) y = 0;  // y 的类型为 const int&&
  1. 如果 exp 是一个左值,或者被括号( )包围,那么 decltype(exp) 的类型就是 exp 的引用;假设 exp 的类型为 T,那么 decltype(exp) 的类型就是 T&。
class Base{
public:int x;
};
int main(){const Base obj;//带有括号的表达式decltype(obj.x) a = 0;  //obj.x 为类的成员访问表达式,符合推导规则一,a 的类型为 intdecltype((obj.x)) b = a;  //obj.x 带有括号,符合推导规则三,b 的类型为 int&。//加法表达式int n = 0, m = 0;decltype(n + m) c = 0;  //n+m 得到一个右值,符合推导规则一,所以推导结果为 intdecltype(n = n + m) d = c;  //n=n+m 得到一个左值,符号推导规则三,所以推导结果为 int&return 0;
}

关于decltype的使用

auto 的语法格式比 decltype 简单,所以在一般的类型推导中,使用 auto 比使用 decltype 更加方便;
但是在一些auto不方便使用的场景下,decltype会更加好用,以下举例

1、auto推导必须初始化变量,而decltype只需要根据表达式即可,如果不想初始化变量即声明类型时;
2、auto 只能用于类的静态成员,不能用于类的非静态成员(普通成员),如果我们想推导非静态成员的类型时(详细的一个例子:http://c.biancheng.net/view/7151.html)
3、decltype 和 auto 结合起来完成返回值类型的推导(具体的例子http://c.biancheng.net/view/3727.html)

二、左值右值

详细的看这个–>左值引用、右值引用、移动语义、完美转发的所有 - - 程序喵大人

  • 左值:可以取地址并且有名字的东西就是左值。
  • 右值:不能取地址的没有名字的东西就是右值。
  • 纯右值:运算表达式产生的临时变量、不和对象关联的原始字面量、非引用返回的临时变量、lambda表达式等都是纯右值。
  • 将亡值:可以理解为即将要销毁的值。
  • 左值引用:对左值进行引用的类型。
  • 右值引用:对右值进行引用的类型。
  • 移动语义:转移资源所有权,类似于转让或者资源窃取的意思,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用。
  • 完美转发:可以写一个接受任意实参的函数模板,并转发到其它函数,目标函数会收到与转发函数完全相同的实参。
  • 返回值优化:当函数需要返回一个对象实例时候,就会创建一个临时对象并通过复制构造函数将目标对象复制到临时对象,这里有复制构造函数和析构函数会被多余的调用到,有代价,而通过返回值优化,C++标准允许省略调用这些复制构造函数。

三、模板的改进

1、模板的右尖括号
C++11之前是不允许两个右尖括号出现的,会被认为是右移操作符,所以需要中间加个空格进行分割,避免发生编译错误。

int main() {std::vector<std::vector<int>> a; // errorstd::vector<std::vector<int> > b; // ok
}

2、模板的别名(using代替typedef)

C++11引入了using,可以轻松的定义别名且简洁易读

typedef std::vector<std::vector<int>> vvi; // before c++11
using vvi = std::vector<std::vector<int>>; // c++11

因为:using 语法和 typedef 一样,并不会创造新的类型,
所以:func_t 定义的 xx_2 并不是一个由类模板实例化后的类,而是 void(*)(int, int) 的别名。

/* C++98/03 */
template <typename T>
struct func_t
{typedef void (*type)(T, T);
};
// 使用 func_t 模板
func_t<int>::type xx_1;/* C++11 */
template <typename T>
using func_t = void (*)(T, T);
// 使用 func_t 模板
func_t<int> xx_2;

除此之外,typedef定义函数指针简直太难读懂!使用using就好很多

typedef void (*func)(int, int); // 啥玩意,看不懂
using func = void (*)(int, int); // 起码比typedef容易看的懂吧

3、函数模板的默认模板参数

C++11之前只有类模板支持默认模板参数,函数模板是不支持默认模板参数的,C++11后都支持。

template <typename T, typename U=int>
class A {T value;  
};template <typename T=int, typename U> // error
class A {T value;  
};

且类模板的默认模板参数必须从右往左定义,而函数模板则没有这个限制。对于函数模板,参数的填充顺序是从左到右的。

template <typename R, typename U=int>
R func1(U val) {return val;
}template <typename R=int, typename U>
R func2(U val) {return val;
}int main() {cout << func1<int, double>(99.9) << endl; // 99cout << func1<double, double>(99.9) << endl; // 99.9cout << func1<double>(99.9) << endl; // 99.9cout << func1<int>(99.9) << endl; // 99cout << func2<int, double>(99.9) << endl; // 99cout << func1<double, double>(99.9) << endl; // 99.9cout << func2<double>(99.9) << endl; // 99.9cout << func2<int>(99.9) << endl; // 99return 0;
}

参考文章:
1. C++新特性汇总–腾讯云
2. C++的auto–c语言中文网
3. C++新特性汇总–知乎

other奇葩小知识

C++以下选项中那种变量类型没有布尔值?
A 、int B、char C、void D、double
答:void 是一种空类型,不可存储具体的值,因此没有布尔值

在C++中,还可以使用 const 关键字来限制类的对象被复制。将类的拷贝构造函数和赋值运算符声明为 const 可以防止对象被复制,但允许对象进行移动语义的操作。此外,也可以将类的拷贝构造函数和赋值运算符声明为删除的,从而完全禁止对象的复制操作。

在C++中,异常规格说明已被弃用,取而代之的是 noexcept 关键字。

noexcept 是一个类型修饰符,用于指定函数是否会抛出异常。如果一个函数被声明为 noexcept,则它保证不会抛出任何类型的异常,包括其内部可能抛出的异常。如果函数确实抛出了异常,程序将调用 std::terminate() 终止程序执行。这有助于提高代码的可读性和可维护性,并允许编译器进行更好的优化。

持续更新中…挖坑…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91552.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Machine learning][Part3] numpy 矢量矩阵操作的基础知识

很久不接触数学了&#xff0c;machine learning需要用到一些数学知识&#xff0c;这里在重温一下相关的数学基础知识 矢量 矢量是有序的数字数组。在表示法中&#xff0c;矢量用小写粗体字母表示。矢量的元素都是相同的类型。例如&#xff0c;矢量不包含字符和数字。数组中元…

在比特币上支持椭圆曲线 BLS12–381

通过使用智能合约实现来支持任何曲线 BLS12–381 是一种较新的配对友好型椭圆曲线。 与常用的 BN-256 曲线相比&#xff0c;BLS12-381 的安全性明显更高&#xff0c;并且安全目标是 128 位。 所有其他区块链&#xff0c;例如 Zcash 和以太坊&#xff0c;都必须通过硬分叉才能升…

C++核心编程

C核心编程 C核心编程1 内存分区模型1.1 程序运行前1.2 程序运行后1.3 new操作符 2 引用2.1 引用的基本使用2.2 引用注意事项2.3 引用做函数参数2.4 引用做函数返回值2.5 引用的本质2.6 常量引用 3 函数提高3.1 函数默认参数3.2 函数占位参数3.3 函数重载3.3.1 函数重载概述3.3.…

【Django 笔记】第一个demo

1. pip 安装 2. django 指令 D:\software\python3\anconda3\Lib\site-packages\django\bin>django-adminType django-admin help <subcommand> for help on a specific subcommand.Available subcommands:[django]checkcompilemessagescreatecachetabledbshelldiff…

精彩回顾 | 迪捷软件亮相2023世界智能网联汽车大会

2023年9月24日&#xff0c;2023世界智能网联汽车大会&#xff08;以下简称大会&#xff09;在北京市圆满落幕。迪捷软件北京参展之行圆满收官。 本次大会由工业和信息化部、公安部、交通运输部、中国科学技术协会、北京市人民政府联合主办&#xff0c;是我国首个经国务院批准的…

WPF中的控件

内容控件&#xff1a;label、border Window控件 Label控件 Border控件 内容控件 Button控件 点击取消按钮关闭程序&#xff1b;点击登录按钮打开BorderWindow窗口。 TextBox控件 PasswordBox控件 TextBlock控件 加载窗口时显示TextBlock中的内容 RadioButton控件 CheckBox控件…

react antd InputNumber只允许输入数字的方法

一、前言 前端项目是react&#xff0c;使用了antd&#xff0c;需要一个数字输入框&#xff0c;只允许输入数字。 二、代码样例 import { Form, InputNumber } from antd;const FormItem Form.Item;const formItemLayout {labelCol: {xs: { span: 24 },sm: { span: 8 },},…

深入探讨java -jar命令:详解及代码演示

引言&#xff1a; 在Java开发中&#xff0c;我们经常需要将多个类打包成一个可执行的jar文件&#xff0c;以便于分发和运行。而使用java -jar命令是一种方便快捷地在命令行中运行Java可执行jar文件的方法。本文将详细介绍java -jar命令的使用方式、原理及提供相关的代码演示和…

Docker清理

title: “Mysql安装” createTime: 2022-01-04T20:07:3108:00 updateTime: 2022-01-04T20:07:3108:00 draft: false author: “name” tags: [“mysql”] categories: [“docker”] description: “测试的” docker-mysql安装部署文档 文章目录 title: "Mysql安装" …

413 Request Entity Too Large问题

问题背景 在某系统中上传文件时&#xff0c;如果文件大小超过了一定范围就会爆 413 Request Entity Too Large 问题。 原因 在使用 nginx 反向代理后台服务时&#xff0c;如果请求体中过大&#xff0c;超过了默认的 1M 则会爆该错误。 解决方案 在 nginx 中&#xff0c;指…

信号类型(雷达)——脉冲雷达(四)

系列文章目录 《信号类型&#xff08;雷达通信&#xff09;》 《信号类型&#xff08;雷达&#xff09;——雷达波形认识&#xff08;一&#xff09;》 《信号类型&#xff08;雷达&#xff09;——连续波雷达&#xff08;二&#xff09;》 《信号类型&#xff08;雷达&…

【Java 进阶篇】深入理解 JDBC:Java 数据库连接详解

数据库是现代应用程序的核心组成部分之一。无论是 Web 应用、移动应用还是桌面应用&#xff0c;几乎都需要与数据库交互以存储和检索数据。Java 提供了一种强大的方式来实现与数据库的交互&#xff0c;即 JDBC&#xff08;Java 数据库连接&#xff09;。本文将深入探讨 JDBC 的…

力扣 -- 10. 正则表达式匹配

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:bool isMatch(string s, string p) {int ms.size();int np.size();//处理后续映射关系s s;//处理后续映射关系p p;vector<vector<bool>> dp(m1,vector<bool>(n1));//初始化dp[0][0]true…

数学相关训练题解

训练链接 CF645F 题目链接 点击打开链接 题目解法 一眼莫反 推式子的步骤就不写了&#xff0c;反正也比较套路 这里只给出最后的式子为&#xff1a; A n s ∑ i 1 V ϕ ( i ) ∗ ( ∑ i ∣ j c n t j k ) Ans\sum\limits_{i1}^{V}\phi(i)*\binom{\sum\limits_{i\mid j}c…

C- 静态链接

静态链接意味着在编译时将所有库函数直接嵌入到最终的可执行文件中&#xff0c;而不是在运行时通过共享库来动态链接这些函数。静态链接的结果是一个更大的可执行文件&#xff0c;因为它包含了所有必要的代码&#xff0c;但它可以在没有外部依赖的情况下独立运行。 下面是一个…

【开发篇】十、Spring缓存:手机验证码的生成与校验

文章目录 1、缓存2、用HashMap模拟自定义缓存3、SpringBoot提供缓存的使用4、手机验证码案例完善 1、缓存 缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质使用缓存可以有效的减少低速数据读取过程的次数&#xff08;例如磁盘IO&#xff09;&#xff0c;提高…

排序算法之【快速排序】

&#x1f4d9;作者简介&#xff1a; 清水加冰&#xff0c;目前大二在读&#xff0c;正在学习C/C、Python、操作系统、数据库等。 &#x1f4d8;相关专栏&#xff1a;C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 &#x1f44d…

Maven路上的疑难杂症

问题一&#xff1a;idea同步jar包提示“Could not find artifact org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:pom:2.1.0.M4 in aliyunmaven”错误&#xff1b; 问题二&#xff1a;本地有maven依赖&#xff0c;idea却扫描不到&#xff1b;…

YOLOv8改进算法之添加CA注意力机制

1. CA注意力机制 CA&#xff08;Coordinate Attention&#xff09;注意力机制是一种用于加强深度学习模型对输入数据的空间结构理解的注意力机制。CA 注意力机制的核心思想是引入坐标信息&#xff0c;以便模型可以更好地理解不同位置之间的关系。如下图&#xff1a; 1. 输入特…

Error: Activity class {xxx.java} does not exist

git切换到不同的branch之后&#xff0c;报下面的错误&#xff1a; Error: Activity class {xxx.java} does not exist 解决方案&#xff1a; 首先clean 然后会删除build目录 然后点击&#xff1a;Invalidate Caches Android Studio重启&#xff0c;然后重新build即可。