首页 > 编程语言 >移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——15.C++11(1)

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

时间:2024-10-27 11:47:07浏览次数:7  
标签:11 std 15 string 右值 int 移情别恋 左值 引用

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

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

标签:11,std,15,string,右值,int,移情别恋,左值,引用
From: https://blog.csdn.net/2301_80374809/article/details/143265453

相关文章

  • 【学术论文投稿】Windows11开发指南:打造卓越应用的必备攻略
    【IEEE出版·南方科技大学】第十一届电气工程与自动化国际会议(IFEEA2024)_艾思科蓝_学术一站式服务平台 更多学术会议论文投稿请看:https://ais.cn/u/nuyAF3目录引言 一、Windows11开发环境搭建二、Windows11关键新特性三、Windows11设计指南四、Windows11开发实战代......
  • Windows11 C盘扩容
    https://www.pcoic.com/system/windows/218.htmlWindows系统内置了一个强大的工具——磁盘管理,下文我将模拟日常需求,分别演示新建、合并分区,以及分配和修改盘符的操作。一、新建分区这是电脑用户最主要的需求。前两三年SSD的价格还比较高,高端电脑普遍采取SSD+HDD的组合......
  • 配置pytorch环境2024-更新至win11
    配置pytorch环境2024windows111.安装anacondacondacreate-n{虚拟环境名}python=3.9matplotlibnumpypandasjupyter我们新建一个python版本为3.9的虚拟环境,初始化安装了matplotlib,numpy,pandas库,以避免后续依次安装而造成的依赖版本冲突问题。Tips:经验得出的结论,......
  • Windows 11 version 24H2 & LTSC 2024 中文版、英文版 (x64、ARM64) 下载 (updated Oc
    Windows11version24H2&LTSC2024中文版、英文版(x64、ARM64)下载(updatedOct2024)Windows11,version24H2,企业版arm64x64请访问原文链接:https://sysin.org/blog/windows-11/查看最新版。原创作品,转载请保留出处。作者主页:sysin.org全新推出Windows11全新......
  • 2024-2025-1 20241311 《计算机基础与程序设计》第5周学习总结
    学期2024-2025-1学号20241311《计算机基础与程序设计》第5周学习总结作业信息这个作业属于哪个课程<班级的链接>2024-2025-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(2024-2025-1计算机基础与程序设计第五周作业)这个作业的目标<写上具体方......
  • 2024-2025-1 20241411王思棋《计算机基础与程序设计》第五周学习总结
    班级链接https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP作业要求https://www.cnblogs.com/rocedu/p/9577842.html#WEEK05教材学习内容总结《计算机科学概论》第六章一、低级程序设计语言概述(一)定义与特点低级程序设计语言是一种更接近计算机硬件的编程......
  • 2024-2025-1 学号20241315《计算机基础与程序设计》第五周学习总结
    作业信息这个作业属于哪个课程[2024-2025-1-计算机基础与程序设计](https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP)这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK05这个作业的目标Pep/9虚拟机机器语言与汇编语言算法与伪代码......
  • redis第152节答疑 redis源码分析String重要总结
    redis的string类型,如果数字大于10000,就不去共享整数中去取,然后就变成了embstr或者raw,为什么不是new一个redisobject,并且编码为int对于Redis的字符串类型(String),当字符串表示的是一个整数值时,Redis会根据具体情况选择不同的编码方式。对于数字大于10000的情况,Redis不会将其编......
  • 11月1日零点国考报名确认,超全流程请收好
    2025国考报名确认已于11月1日0:00开始已经报完名且通过资格审核的小伙伴们一定要及时确认!具体流程是什么?操作时需要注意哪些事项?看完这篇就能全部搞定~25国考时间轴线✔️报名时间:10月15日8:00至10月24日18:00✔️审查时间:10月15日8:00至10月26日18:00✔️查询报名号:2024......
  • 南昌航空大学-软件学院-22207112-卢翔-JAVAPTA(1-3)博客
    目录前言PTA第一次作业(7-5答题判题程序-1)设计与分析题目分析知识点解析调试过程时序图,耦合度改进建议PTA第二次作业设计与分析题目分析知识点解析(不重复)调试过程类图,耦合度改进建议PTA第三次作业设计与分析题目分析知识点解析调试过程类图,耦合度改进建议踩坑心得总结前言本次的......