首页 > 编程语言 >C++11实用特性1

C++11实用特性1

时间:2023-08-09 09:00:31浏览次数:38  
标签:11 int auto C++ 实用 类型 using 表达式

1 原始字面量

有时候在输出一个路径字符串时,编译器会将其中的部分内容识别成转义字符进行输出,可以用R “xxx(原始字符串)xxx”其中()两边的字符串可以省略。原始字面量R可以直接表示字符串的实际含义,而不需要额外对字符串做转义或连接等操作。

string str2 = R"(D:\hello\world\test.text)";

2 nullptr

在之前的C++中,为指针进行初始化的时候通常用NULL,在C语言中NULL的本质是一个(void*)0,而在C++中NULL的本质就是0,一个int类型值,底层实现为:

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

因为C++中不允许一个void *指针隐式转换为其它类型指针,比如:

void *ptr1 = NULL;
int *ptr2 = ptr1;//错误
int *ptr2 = (int *)ptr1;//正确

C++11没有对这一特性进行修改,而是引入了nullptr专门用于初始化空类型指针,其可以隐式转换为其它类型的指针,从而避免了野指针(没有明确指向的指针)

3 constexpr

const在C++11之前就有,用处在于变量只读以及修饰常量,但要注意两者是不一样的

变量只读:比如函数中我们不希望传入的参数被修改
void func(const int num)

修饰常量:有时提前定义一个常量,并用于描述数组大小
const int a = 20;
int arr[a];

 
C++11中用constexpr修饰常量表达式,常量表达式指的就是由多个(≥1)常量(值不会改变)组成并且在编译过程中就得到计算结果的表达式。其效率高于运行时计算的非常量表达式,其不需要每次运行都计算

要注意的时是,constexpr不能取代const,在表示常量的时候,两者是相同的,但是在用于变量只读的时候,比如引用传参的时候设置只读属性还是用const,constexpr达不到修饰变量只读的效果。

4 auto自动类型推导

使用auto声明的变量必须要进行初始化,以让编译器推导出它的实际类型,在编译时将auto占位符替换为真正的类型。

auto的使用限制

  • 不能作为函数参数使用。因为只有在函数调用的时候才会给函数参数传递实参,auto要求必须要给修饰的变量赋值,因此二者矛盾。
  • 不能用于类的非静态成员变量的初始化
  • 不能使用auto关键字定义数组
  • 无法使用auto推导出模板参数

auto的应用

  • 用于泛型编程,在使用模板的时候,很多情况下我们不知道变量应该定义为什么类型就用auto
  • 用于stl容器的遍历
#include <map>
int main()
{
    map<int, string> person;
    map<int, string>::iterator it = person.begin();
    for (; it != person.end(); ++it)
    {
        // do something
    }
    return 0;
}

//简化后为:
    map<int, string> person;
    // 代码简化
    for (auto it = person.begin(); it != person.end(); ++it)
    {
        // do something
    }

5 decltype类型推导

使用auto只能进行初始化变量的推导,而decltype可以进行表达式的推导,其也是在编译阶段实现的

推导规则

  • 表达式为普通变量或者普通表达式或者类表达式,在这种情况下,使用decltype推导出的类型和表达式的类型是一致的。
  • 表达式是函数调用,使用decltype推导出的类型和函数返回值一致。
  • 表达式是一个左值,或者被括号( )包围,使用 decltype推导出的是表达式类型的引用(如果有const、volatile限定符不能忽略)。

6 final和override

C++中增加了final关键字来限制某个类不能被继承,或者某个虚函数不能被重写,如果使用final修饰函数,只能修饰虚函数,并且要把final关键字放到类或者函数的后面。

override关键字确保在派生类中声明的重写函数与基类的虚函数有相同的签名,同时也明确表明将会重写基类的虚函数,这样就可以保证重写的虚函数的正确性,也提高了代码的可读性,和final一样这个关键字要写到方法的后面。使用了override关键字之后,假设在重写过程中因为误操作,写错了函数名或者函数参数或者返回值编译器都会提示语法错误

7 函数模板允许默认参数

8 using

在C++中using用于声明命名空间,使用命名空间也可以防止命名冲突。在程序中声明了命名空间之后,就可以直接使用命名空间中的定义的类了。C++11中用using可以来定义类型的别名,和typedef的效果一样

typedef 旧的类型名 新的类型名;
// 使用举例
typedef unsigned int uint_t;

using 新的类型 = 旧的类型;
// 使用举例
using uint_t = int;

 
其好处体现在函数指针的定义上

// 使用typedef定义函数指针
typedef int(*func_ptr)(int, double);

// 使用using定义函数指针
using func_ptr1 = int(*)(int, double);

使用using定义函数指针别名的写法看起来就非常直观了,把别名的名字强制分离到了左边,而把别名对应的实际类型放在了右边,比较清晰,可读性比较好。

但using最主要的特性还是可以通过使用using来为一个模板定义别名,比如:

template <typename T>
using mymap = map<int, T>;

使用typedef重定义类似很方便,但是它有一点限制,比如无法重定义一个模板,比如我们需要一个固定以int类型为key的map,它可以和很多类型的value值进行映射,如果使用typedef这样直接定义就非常麻烦:

typedef map<int, string> m1;
typedef map<int, int> m2;
typedef map<int, double> m3;

9 基于范围的for循环

基本语法

for (declaration : expression)
{
    // 循环体
}

在上面的语法格式中declaration表示遍历声明,在遍历过程中,当前被遍历到的元素会被存储到声明的变量中。expression是要遍历的对象,它可以是表达式、容器、数组、初始化列表等。

通常建议以引用的方式进行修改,不仅可以对其进行写操作,而且还避免了每次遍历的拷贝操作。

#include <iostream>
#include <vector>
using namespace std;

int main(void)
{
    vector<int> t{ 1,2,3,4,5,6 };
    cout << "遍历修改之前的容器: ";
    for (auto &value : t)
    {
        cout << value++ << " ";
    }
    cout << endl << "遍历修改之后的容器: ";

    for (auto &value : t)
    {
        cout << value << " ";
    }
    cout << endl;

    return 0;
}

对容器的遍历过程中,如果只是读数据,不允许修改元素的值,可以使用const定义保存元素数据的变量,在定义的时候建议使用const auto &,这样相对于const auto效率要更高一些。

#include <iostream>
#include <vector>
using namespace std;

int main(void)
{
    vector<int> t{ 1,2,3,4,5,6 };
    for (const auto& value : t)
    {
        cout << value << " ";
    }

    return 0;
}

使用普通的for循环方式(基于迭代器)遍历关联性容器, auto自动推导出的是一个迭代器类型,需要使用迭代器的方式取出元素中的键值对(和指针的操作方法相同):

  • it->first
  • it->second
    使用基于范围的for循环遍历关联性容器,auto自动推导出的类型是容器中的value_type,相当于一个对组(std::pair)对象,提取键值对的方式如下:
  • it.first
  • it.second

普通循环与基于范围循环的区别:
对应基于范围的for循环来说,冒号后边的表达式只会被执行一次。在得到遍历对象之后会先确定好迭代的范围,基于这个范围直接进行遍历。如果是普通的for循环,在每次迭代的时候都需要判断是否已经到了结束边界。

10

标签:11,int,auto,C++,实用,类型,using,表达式
From: https://www.cnblogs.com/dreamer-q/p/17615631.html

相关文章

  • 【随手记】Mybatis报错 错误信息:ORA-00911: 无效字符
    注意@param注解是属于哪个包的这个有的时候会有影响接收不到参数xml里面不要加分号查了半天Bug最后发现是xml里面的sql语句后面加了个;,删掉就好了。......
  • t113-c-wpa_cli遇到问题
    1.Failedtoconnecttonon-globalctrl_ifname:wlan0 error:Nosuchfileordirectory之前没注意到,wpa_cli在连上网络的时候还可以用,但是连不上了连查询存储的wlan都不行。那么我在这篇文章中找到与我相同的问题:https://blog.csdn.net/u010299133/article/details/10582......
  • C++类和对象_多态
    虚函数被virtual修饰的成员函数被称为虚函数,虚函数的地址会被纳入类的虚函数表(virtualfunctiontable)。inline和virtual不会同时生效,用virtual修饰内联函数时,编译器会忽视函数的内联属性,此时函数不再是内联。虚函数一定不是内联函数。虚函数的重写子类继承父类,并有一个与父类......
  • C++ Primer Plus 第6版 读书笔记(8)第 8章 函数探幽
    第8章函数探幽本章内容包括:内联函数。引用变量。如何按引用传递函数参数。默认参数。函数重载。函数模板。函数模板具体化。通过第7章,您了解到很多有关C++函数的知识,但需要学习的知识还很多。C++还提供许多新的函数特性,使之有别于C语言。新特性包括内联函数、......
  • Unity 编辑器资源导入处理函数 OnPostprocessAudio :深入解析与实用案例
    Unity编辑器资源导入处理函数OnPostprocessAudio用法点击封面跳转下载页面简介在Unity中,我们可以使用编辑器资源导入处理函数(OnPostprocessAudio)来自定义处理音频资源的导入过程。这个函数是继承自AssetPostprocessor类的,通过重写这个函数,我们可以在音频资源导入完成后执......
  • Unity 编辑器资源导入处理函数 OnPostprocessAudio :深入解析与实用案例
    Unity编辑器资源导入处理函数OnPostprocessAudio用法点击封面跳转下载页面简介在Unity中,我们可以使用编辑器资源导入处理函数(OnPostprocessAudio)来自定义处理音频资源的导入过程。这个函数是继承自AssetPostprocessor类的,通过重写这个函数,我们可以在音频资源导入完成后执......
  • Unity的UnityStats: 属性详解与实用案例
    UnityStats属性详解UnityStats是Unity引擎提供的一个用于监测游戏性能的工具,它提供了一系列的属性值,可以帮助开发者解游戏的运行情况,从而进行优化。本文将详细介绍UnityStats的每个属性值,并提供多个使用例子帮助开发者更好地使用UnityStats。帧率相关属性UnityStats.fps......
  • 【C++第三方库】Windows下编译和使用websocketpp
    应用场景:使用C++开发一个支持websocket协议的服务进程,可与HTML5(浏览器js文件)通信。来实现替换基于firebreath框架的跨浏览器插件开发。当前,讲述websocketpp开源库的应用。目的是为了实现C++进程,支持websocket协议。但WebSocketpp是一个开源库,依赖于Boost和OpenSSL资源准......
  • 111
    #include<bits/stdc++.h>usingnamespacestd;intmaxH=8,maxL=8,l=maxH/2,h=maxL/2;voidv(inth1,intl1){for(inti=0;i<maxH;i++){for(intj=0;j<maxL;j++){if(i==h&&j==l){cout<&......
  • FX110讯: Finveo放弃英国FCA牌照,决定退出英国市场
    土耳其投资控股公司InveoInvestmentHolding旗下零售货币对和差价合约(CFD)经纪商Finveo已放弃其FCA牌照,决定退出英国市场。上月,行业知名经纪商ADSS也宣布放弃了FCA牌照,原因是其英国子公司几位重要高管的离职以及经营状况不善。Finveo放弃FCA牌照的原因与ADSS类似。据悉,该公司英国团......