移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——15.C++11(1)

news2024/10/28 8:09:39

1. 自动类型推导 (auto)

C++11 引入了 auto 关键字,可以根据初始值的类型自动推导变量的类型,从而减少了手动声明类型的繁琐。例如:

std::vector<int> vec = {1, 2, 3, 4};
auto it = vec.begin();  // 自动推导类型为 std::vector<int>::iterator

auto 的引入使代码更加简洁和易读,特别是在遇到长类型名称时,极大地提高了开发效率

2. 范围循环 (Range-based for Loop)

C++11 引入了范围循环,可以轻松遍历容器中的元素,而不需要手动编写迭代器代码。例如:

std::vector<int> vec = {1, 2, 3, 4};
for (auto value : vec) {
    std::cout << value << " ";
}

范围循环使代码更加简洁,避免了循环中易出现的迭代器错误。

3.std::initializer_list

文档介绍
std::initializer_list 是 C++11 引入的一种模板类,用于支持初始化列表(initializer list)。它允许使用大括号 {} !!!将一组值直接传递给构造函数或函数,从而简化代码书写。

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;
class MyClass {
public:
    MyClass(std::initializer_list<int> list) {
        for (auto& elem : list) {
            // 处理每个元素
        }
    }
};

MyClass obj = {1, 2, 3, 4}; // 通过初始化列表构造对象

4.STL中一些变化

在这里插入图片描述

4.1 array

C++11 中引入的 std::array 是标准模板库(STL)中的一个容器类,提供了一个固定大小的数组,具有数组的简单性和 STL 容器的功能。它被定义在头文件 中。

std::array 的主要特点包括:

1.固定大小:std::array 的大小在编译时确定,一旦定义后不能改变。它是栈分配的数组,适合需要固定大小的数组场景。

std::array<int, 5> arr = {1, 2, 3, 4, 5}; // 定义一个包含5个整数的array

2.安全性:与 C 风格的数组相比,std::array 提供了更好的边界安全性,可以使用 at() 方法访问元素,该方法会进行边界检查

int x = arr.at(2); // 如果越界,抛出异常

4.1 forward_list(单链表)

C++11 中的 std::forward_list 是一个单向链表容器,定义在头文件 <forward_list> 中。与 std::list(双向链表)相比,std::forward_list 仅支持单向链表结构,更加轻量。

std::forward_list<int> flist = {1, 2, 3};
flist.push_front(0);  // 在头部插入元素

5.右值引用和移动语义

5.1左值引用和右值引用

无论左值引用还是右值引用,都是给对象取别名。

什么是 左值 ?什么是 左值引用

左值是一个表示数据的表达式(如变量名或解引用的指针),我们可获取它的地址+可以对它赋值
1.左值可以出现赋值符号的左边,
2.右值不能出现在赋值符号左边。
定义时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;
}

什么是 右值 ?什么是 右值引用

右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址

int main()
{
double x = 1.1, y = 2.2;
// 以下几个都是常见的右值
10;
x + y;
fmin(x, y);
// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值
10 = 1;
x + y = 1;
fmin(x, y) = 1;
return 0;
}

5.2左值引用与右值引用比较

左值引用 总结:

  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;
}

在这里插入图片描述

5.3右值引用使用场景和意义

左值引用的使用场景:

void func1(bit::string s)
{}
void func2(const bit::string& s)
{}
int main()
{
 bit::string s1("hello world");
 // func1和func2的调用我们可以看到左值引用做参数减少了拷贝,提高效率的使用场景和价值
 func1(s1);
 func2(s1);
 // string operator+=(char ch) 传值返回存在深拷贝
 // string& operator+=(char ch) 传左值引用没有拷贝提高了效率
 s1 += '!';
 return 0;
}

参数和做返回值都可以提高效率。

左值引用的短板:

但是当函数返回对象是一个 局部变量 ,出了函数作用域就不存在了,就不能使用左值引用返回, 只能 传值返回

在这里插入图片描述
但都需要进行拷贝构造,生成新空间,释放旧空间

在这里插入图片描述

右值引用和移动语义解决上述问题:

移动构造本质是将 参数右值的资源窃取过来 ,占位已有,那么就不 用做深拷贝了,所以它叫做 移动构造,就是窃取别人的资源来构造自己

// 移动构造
string(string&& s)
 :_str(nullptr)
 ,_size(0)
 ,_capacity(0)
{
 cout << "string(string&& s) -- 移动语义" << endl;
 swap(s);
}
int main()
{
 bit::string ret2 = bit::to_string(-1234);
 return 0;
}

这里没有调用深拷贝的拷贝构造,而是调用了移动构造,移动构造中没有新开空间,拷贝数据,所以效率提高了

在这里插入图片描述

不仅仅有移动构造,还有移动赋值:

// 移动赋值
string& operator=(string&& s)
{
 cout << "string& operator=(string&& s) -- 移动语义" << endl;
 swap(s);
 return *this;
}
int main()
{
 bit::string ret1;
 ret1 = bit::to_string(1234);
 return 0;
}
// 运行结果:
// string(string&& s) -- 移动语义
// string& operator=(string&& s) -- 移动语义

右值被右值引用的结果是左值!!!!!!!!!!!

在这里插入图片描述

5.4模板中的&& 万能引用

void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }
void Fun(int &&x){ cout << "右值引用" << endl; }
void Fun(const int &&x){ cout << "const 右值引用" << endl; }
// 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
// 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
template<typename T>
void PerfectForward(T&& t)
{
 Fun(t);
}
int main()
{
 PerfectForward(10);           // 右值
 int a;
 PerfectForward(a);            // 左值
 PerfectForward(std::move(a)); // 右值
 const int b = 8;
 PerfectForward(b);      // const 左值
 PerfectForward(std::move(b)); // const 右值
 return 0;
}

结果输出全是左值!!!

解决方法:

std::forward 完美转发 在传参的过程中保留对象原生类型属性

void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }
void Fun(int &&x){ cout << "右值引用" << endl; }
void Fun(const int &&x){ cout << "const 右值引用" << endl; }
// std::forward<T>(t)在传参的过程中保持了t的原生类型属性。
template<typename T>
void PerfectForward(T&& t)
{
 Fun(std::forward<T>(t));
}
int main()
{
 PerfectForward(10);           // 右值
 int a;
 PerfectForward(a);            // 左值
 PerfectForward(std::move(a)); // 右值
 const int b = 8;
 PerfectForward(b);      // const 左值
 PerfectForward(std::move(b)); // const 右值
 return 0;
 }

6.新的类功能

原来C++类中,有6个默认成员函数:

  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址重载
  6. const 取地址重载

C++11 新增了两个:7.移动构造函数和8.移动赋值运算符重载

针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:

  1. 如果你没有自己实现移动构造函数,且没有实现析构函数,拷贝构造,拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造, 如果实现了就调用移动构造,没有实现就调用拷贝构造。
  2. 如果你没有自己实现移动赋值重载函数,且没有实现析构函数拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似)
  3. 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。
class Person
{
public:
 Person(const char* name = "", int age = 0)
 :_name(name)
 , _age(age)
 {}
 /*Person(const Person& p)
 :_name(p._name)
 ,_age(p._age)
 {}*/
 
 /*Person& operator=(const Person& p)
 {
 if(this != &p)
 {
 _name = p._name;
 _age = p._age;
 }
 return *this;
 }*/
 
 /*~Person()
 {}*/
private:
 bit::string _name;
 int _age;
};
int main()
{
 Person s1;
 Person s2 = s1;
 Person s3 = std::move(s1);
 Person s4;
 s4 = std::move(s2);
 return 0;
}

剩下的内容等到下一期再详细讲解

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

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

相关文章

C++类和对象 (中)

文章目录 前言一. 类的默认成员函数1.1 构造函数概念特点 1.2 析构函数定义与特点作用注意 1.3 拷贝构造函数概念特性 2. 赋值运算符重载2.1 运算符重载特性注意 2.2 赋值运算符重载定义特性 2.3 流运算符重载概念注意 3. 日期类实现4. const成员函数概念注意 5. 取地址运算符重…

【c++丨STL】string模拟实现(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 一、头文件&#xff08;成员变量与函数声明&#xff09; 二、源文件&#xff08;功能实现&#xff09; 交换两字符串 构造函数 拷贝构造…

人工智能进程;算子加速的具体计算部分;大模型GPT5:参数18万亿;大模型面临问题

目录 人工智能进程 算子加速的简单理解,举例说明 一、简单理解 二、举例说明 一、算子加速的具体计算部分 二、举例说明 三、算子加速是否仅针对GPU 大模型GPT5:参数18万亿 大模型面临问题 算力集群设计框架 人工智能进程

【c++高级篇】--多任务编程/多线程(Thread)

目录 1.进程和线程的概念&#xff1a; 1.1 进程&#xff08;Process&#xff09;&#xff1a; 1.2线程&#xff08;Thread&#xff09;&#xff1a; 1.3 对比总结&#xff1a; 2.多线程编程&#xff1a; 2.1 基于线程的多任务处理&#xff08;Thread&#xff09;&#xf…

jenkins ssh 免密报错Host key verification failed.

jenkins 发布项目&#xff0c;ssh连接远程服务器时报错&#xff1a;Host key verification failed. 解决&#xff1a; 原因是生成的sshkey不是用的jenkins用户&#xff0c;所以切换用户到&#xff1a;jenkins重新生成sshkey su jenkins ssh-keygen -t rsa ssh-copy-id -i ~/…

Linux: Shell编程入门

Shell 编程入门 1 ) Shell 概念 shell 是 在英语中 壳, 外壳的意思可以把它想象成嵌入在linux这样的操作系统里面的一个微型的编程语言不像C语言, C 或 Java 等编程语言那么完整&#xff0c;它可以帮我们完成很多自动化任务例如保存数据监测系统的负载等等&#xff0c;我们同样…

MATLAB生物细胞瞬态滞后随机建模定量分析

&#x1f3af;要点 基于随机动态行为受化学主方程控制&#xff0c;定量分析单细胞瞬态效应。确定性常微分方程描述双稳态和滞后现象。通过随机性偏微分方程描述出暂时性滞后会逐渐达到平稳状态&#xff0c;并利用熵方法或截断方法计算平衡收敛速度的估计值。随机定量分析模型使…

什么是字节序、大小端、高低字节、高低地址?

目录 1. 什么是字节序&#xff08;Endianness&#xff09;&#xff1f; 2. 什么是大小端&#xff08;Big-Endians and Little-Endian&#xff09;&#xff1f; 3. 什么时候需要用到大小端的概念&#xff1f; 4. 如何确认系统的大小端模式&#xff1f; 5. 什么是大小端定义…

[LVGL] MessageBox

该例子用lvgl9 来测试&#xff0c;对话框从底部升上来。当点击关闭或者确认按键时&#xff0c;会向绑定对象发送按键事件&#xff0c;参数 100/101. /*** file lv_demo_test.c**/#include "stdio.h" #include "stdlib.h" #include "lvgl.h"#ifde…

985研一,转嵌入式好还是后端开发好?

有个老铁问&#xff0c;985研一&#xff0c;转嵌入式好还是后端开发好&#xff1f; 我认为&#xff0c;这学历&#xff0c;两个随便挑&#xff0c;我说的&#xff0c;从趋势来看&#xff0c;更建议嵌入式&#xff0c;走供应链上游&#xff0c;芯片原厂、新能源车企、军工或者搞…

IDEA自动生成时序图插件-SequenceDiagram

目录 前言介绍安装在线安装离线安装 使用基本使用使用技巧 知识扩展为什么要画时序图&#xff1f;为什么要使用SequenceDiagram插件&#xff1f; 前言 工欲善其事&#xff0c;必先利其器&#xff0c;用对工具&#xff0c;事半功倍。我向大家介绍一款卓越的插件——Sequence Dia…

衡石分析平台系统分析人员手册-展示类控件创建富文本攻略

富文本​ 富文本控件是一种常见的控件&#xff0c;可用来展示文本信息、用户属性信息&#xff0c;在数据分析中起到辅助分析的功能。 富文本常见的使用场景有&#xff1a; 仅展示纯文本信息。在富文本中展示数据集字段、指标、参数等信息。使用富文本展示用户属性相关信息。在…

H3m-Blog

H3m-Blog 一、项目介绍 1.1 项目介绍 一个基于SpringBoot和Vue3的博客系统&#xff0c;博客名称来源于陈奕迅于2009年发布的粤语专辑《H3M》 1.2 技术架构 主要技术栈&#xff1a; SpringBoot2 Vue3 MySQL8.0 1.3 主要功能 内容丰富&#xff0c;尽情体验~ 二、快速开始…

Win11安装基于WSL2的Ubuntu

1. 概述 趁着还没有完全忘记&#xff0c;详细记录一下在Win11下安装基于WSL2的Ubuntu的详细过程。不得不说WSL2现在被微软开发的比较强大了&#xff0c;还是很值得安装和使用的&#xff0c;笔者就通过WSL2安装的Ubuntu成功搭建了ROS环境。 2. 详论 2.1 子系统安装 在Win11搜…

【HarmonyOS NEXT】使用 Navigation 对折叠屏设备页面进行分栏展示,优化 UI 交互

关键词&#xff1a;折叠屏、navigation、router、路由、分栏、UI 随着科技的发展&#xff0c;手机设备形态也由一面屏向多面屏进行发展&#xff0c;那么软件的UI适配也面临着问题&#xff0c;本篇文章主要解决大屏设备的页面 UI 适配问题&#xff0c;如折叠屏&#xff0c;平板&…

MySql数据库中数据类型

本篇将介绍在 MySql 中的所有数据类型&#xff0c;其中主要分为四类&#xff1a;数值类型、文本和二进制类型、时间日期、String 类型。如下&#xff08;图片来源&#xff1a;MySQL数据库&#xff09;&#xff1a; 目录如下&#xff1a; 目录 数值类型 1. 整数类型 2. …

[MoeCTF 2022]endian

查看发现是64位文件&#xff0c;且看到了amd64-64-little&#xff08;这里是小端序&#xff09; 所以我们要反向输入 对于整数 0x12345678&#xff0c;在小端序存储下的内存布局为&#xff1a; 地址 内容 低地址 0x78 0x56 0x34 高地址 0x12 查看main函数&#xff0c…

Python4

4. 更多控制流工具 除了刚介绍的 while 语句&#xff0c;Python 还用了一些别的。我们将在本章中遇到它们。 4.1. if 语句 if elif else if x<0: x 0 print(Negative changed to zero) elif x0: print( zero) else: print(More) 4.2. for 语句 Pyth…

游戏服务器被攻击有办法防护吗

游戏服务器受到攻击时比较常见的。就算是刚上线的游戏&#xff0c;都会有被攻击的时候。游戏服务器受到攻击的原因以及解决方案有哪些呢&#xff1f; 游戏服务器被攻击的原因有哪些呢&#xff1f; 1、常见的攻击&#xff0c;大部分来自于同行之间的恶意竞争&#xff0c;你的游…

Rust 力扣 - 3. 无重复字符的最长子串

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们需要记录当前子串的开始下标&#xff0c;一个哈希表记录字符和遍历过程中最后一次出现的索引 遍历字符串&#xff0c;如果在当前字符在哈希表中有记录&#xff0c;并且索引下标大于当前子串的开始下标&…