当前位置: 首页 > news >正文

c++11新标准、STL

一、c与c++标准简介

C语言的重要3个标准

c89标准(ANSI C)

c99标准(国际标准化组织(ISO)和IEC)这是第二个官方标准

c11标准,原名C1X。这是C语言的第三个官方标准,也是最新标准

二、c++11的常用特性

1、auto关键字

做类型的自动推导,根据值来推导变量的类型,不能单独使用

注意;

1、使⽤ auto 类型推导的变量必须⻢上初始化,这类似于const关键字。

2、auto不能与其它任何类型说明符⼀起使⽤;

3、auto不能被声明为返回值,auto不能作为形参,auto不能被修饰为模板参数

4、C++98标准中auto关键字⽤于⾃动变量的声明,但由于使⽤极少且多余,在 C++17 中已删除这⼀⽤法。

5、auto仅仅是⼀个占位符,它并不是⼀个真正的类型,不能使⽤⼀些以类型为操 作数的操作符,如sizeof或者typeid。

#include <iostream>
#include <string>
#include<fstream>//string.h
using namespace std;//cout cin   std::cout std::cintemplate<class T ,class K>
void test(T a,K b)
{auto ret=  a* b; //另一个是对比较长的类型可以做简化}int main()
{//做类型的自动推导,根据值来推导变量的类型auto a = 3;// int a=3;  //auto做类型推到 必须给变量赋值auto b = 3.3;//double int b=3.3//auto int c = 3; 错的  推到时 不能指定变量类型return 0;
}

2、nullptr关键字

NULL在C++表示空指针,变量值为0的指针,它不指向任何的对象或者函数. NULL通常被定义为:#define NULL ((void *)0) 定义空指针的主要⽤途是避免指针变量的⾮法引⽤,在程序中常作为状态⽐较。

之前C++中⽤0来代表空指针,但是在重载整形的情况下,会出现上述的问题。所 以,C++11加⼊了nullptr,可以保证在任何情况下都代表空指针。 ⽽引⼊了nullptr,这个问题就得到了真正解决,会很顺利的调到void f(void*)这个 版本。

void test(int a)
{}void test(int* a)
{}int main()
{//test(NULL);//NULL对C++重载产生了影响,为了解决这个问题,C++提供了一个新的关键字来表示空指针test(nullptr);//在C++中,如果要对某个指针变量初始化为空指针,尽量使用nullptrint* pt = nullptr; //将pt初始化为空指针return 0;
}

3、for循环新语法

c++11增加了基于范围的for循环,如果在循环中修改数组或容器的每个元素,可使用引用类型

declaration :表示此处要定义⼀个变量,该变量的类型为要遍历序列中存储元 素的类型,需要注意的是在C++11标准中,declaration参数处定义的变量类型可 以⽤auto 关键字表示,该关键字可以使编译器⾃⾏推导该变量的数据类型。

expression:表示要遍历的序列,常⻅的可以为事先定义好的普通数组或者容 器,还可以是⽤0⼤括号初始化的序列。 for循环的这种使⽤⽅式的内在实现实际上还是借助迭代器 列表初始化(List lnitialization)是⼀种通过使⽤⼤括号 {}来初始化变量的⽅法。它 是C++11引⼊的特性,提供了更加统⼀且类型安全的初始化⽅式。通常⽤于初始化 标准库容器。列表初始化的安全主要体现在防⽌窄化转换,例如,从double到 int,列表初始化会发⽣编译错误,⽽传统的初始化则不会(会⾃动进⾏窄化转 换)。 窄化转换是指将⼀个较⼤的类型(如double)转换为较⼩类型可能会丢失数据,为 便⾯这种⻛险,列表初始化在发现窄化转换时会⽣成编译错误。 T var = {value}; //列表初始化 T var{value}; ●

(元素类型:元素体)

基于容器做遍历

int main()
{int arr[3] = { 11,22,33 };for (int a : arr) //主要基于容器来进行遍历{cout << a << endl;//它的循环次数和容器中的元素个数是有关的}string temp = "wajiayi";//首先从容器中取出一个元素,赋值给变量e 然后执行循环体,然后在取出元素,再赋值,再执行循环体,直到元素取完为止。for (auto e : temp){cout << e << endl;}for (auto e : { 11,3,5,6 }){cout << e << endl;}return 0;
}

4、列表初始化

通过{}来初始化变量的方式,是c++引入的特性

列表初始化(List lnitialization)是⼀种通过使⽤⼤括号 {}来初始化变量的⽅法。它 是C++11引⼊的特性,提供了更加统⼀且类型安全的初始化⽅式。通常⽤于初始化 标准库容器。列表初始化的安全主要体现在防⽌窄化转换,例如,从double到 int,列表初始化会发⽣编译错误,⽽传统的初始化则不会(会⾃动进⾏窄化转 换)。 窄化转换是指将⼀个较⼤的类型(如double)转换为较⼩类型可能会丢失数据,为 便⾯这种⻛险,列表初始化在发现窄化转换时会⽣成编译错误。

struct stu
{string name;int math;int chinese;
};int main()
{stu s1{"laogu", 11,22};cout << s1.math << s1.chinese << endl;return 0;
}

5、override关键字

在C++11中,可使⽤虚说明符 override 指出您要覆盖⼀个虚函数,override就是辅 助检查是否正真重写了继承的虚函数。说明符 override 和 final 并⾮关键字,⽽是具有特 殊含义的标识符。 在派⽣类的成员函数中使⽤override时,如果基类中⽆此函数, 或基类中的函数并不是虚函数,编译器会给出相关错误信息

6、delete关键字

对于 C++ 的类,如果程序员没有为其定义特殊成员函数,那么在需要用到某个特殊成员函数的时候,编译器会隐式的自动生成一个默认的特殊成员函数,比如默认的构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。为了能够让程序员显式的禁用某个函数,C++11标准引入了一个新特性:deleted函数。程序员只需在函数声明后加上=delete就可将该函数禁用。

7、default关键字(需要修改)

在C++98和C++03编译器在类中会隐式地产⽣四个函数:默认构造函数、拷⻉构 造函数、析构函数和赋值运算符函数,它们被称为特殊成员函数。 C++引⼊的default关键字,可显示地、强制地要求编译器为我们⽣成默认版本。如果程序员没有显式地为⼀个类定义某个特殊成员函数,⽽⼜需要⽤到该特殊成员 函数时,则编译器会隐式的为这个类⽣成⼀个默认的特殊成员函数

系统如果定义了构造函数,编译器不会再自动生成默认构造函数。仅适用于类的特殊成员函数,且该特殊成员函数没有默认参数

8、noexcept运算符

C++11新标准引⼊的noexcept运算符,可以⽤于指定某个函数不抛出异常。预先知 道函数不会抛出异常有助于简化调⽤该函数的代码,⽽且编译器确认函数不会抛出 异常,它就能执⾏某些特殊的优化操作。 注意:在成员函数中,noexcept需要跟在const以及引⽤限定符之后,在final、 override或虚函数=0之前。noexcept可以出现在该函数的所有的声明或定义语句 中。c++11已经废弃void tun()throw()这种不抛出异常⽅式。

9、匿名函数

匿名函数也称为Lambda函数,可以免去函数的声明和定义。这样匿名函数仅在调中用函数的时候才会创建函数对象,而调用结束后立即释放,所以匿名函数比非匿名函数更节省空间。

Lambda函数表达式具体形式如下
[capture]parametersy-> return-type {body}
//[捕获区](参数区){代码区};

与普通函数差别主要有两个,使⽤ [] 替代了函数名;没有声明返回类型。返回类型相当于使⽤ decltype 根据返回值推断得到的,l 。如果 Lambda 不包含返回语句,推断出的返回类型将为 void 。

注意;当parameters为空的时候,()可以被省去,当body只有"return"或者返回为void, 那么"->return-type"可以被省去。


bool mytest(int val)
{if (val > 100)return true;elsereturn false;}void find(int* arr, int size, bool(*fun)(int)){for (int i = 0; i < size; i++){if (fun(arr[i]))return;}return;}int main()
{int arr[2];find(arr, 2, mytest);//匿名函数一般主要用来做函数的实参return 0;
}
int add(int a, int b)
{return a + b;
}int test(int k, int(*fun)(int, int),int aa,int bb)
{return fun(aa, bb) + k;}
int main()
{cout<<add(10, 20)<<endl;//匿名函数的定义:[](int a, int b)->int {return a + b; };//匿名函数的调用//auto fun= [](int a, int b)->int {return a + b; };//auto fun = [](int a, int b) {return a + b; }; //在匿名函数中 ->返回类型 可以省略, 捕获区中的内容也可以省略//cout<<fun(30, 40);//匿名函数一般主要用来做函数的实参,对于逻辑较简单,代码量比较少的函数适合做成匿名函数cout<<test(10, [](int a, int b) {return a + b; }, 3, 5);return 0;
}

int p = 1000;
int main()
{int a = 10;int bb = 3;//在匿名函数体中不能直接使用外部的局部变量,如果需要使用,需要捕获//在匿名函数体使用的变量可以来自于自身的形参,也可以来自当前文件中的全局变量// auto fun=[](int b) {cout<<b+p + 1; };//fun(33);//--------------------------------//在匿名函数体中要使用外部的局部变量,需要先捕获 后使用//在捕获区如果直接写外部的局部变量名 ,这种捕获方式 叫 按值捕获//特点:在匿名函数体中,只能读捕获的值 不可以对其修改。//当需要捕获多个值  ,彼此之间用逗号去隔开auto fun = [a,bb](int b) {cout << b + a +bb+ 1; };fun(10);return 0;
}

10、右值引用

C++ 右值引⽤是 C++11 引⼊的⼀项重要特性,它主要⽤于实现移动语义和完美转 发,有效解决了传统 C++ 中存在的临时对象拷⻉问题,显著提升了程序性能。 什么是左值与右值 要理解右值引⽤,⾸先得区分左值(lvalue)和右值(rvalue),区分⼀个表达式 是左值还是右值,最简便的⽅法就是看能不能够对它取地址或对它进⾏赋值的操 作:如果能,就是左值;否则,就是右值。⽐如定义的变量就是属于左值,字⾯量 就是右值,临时变量。

右值引⽤(rvalue reference,&&)跟传统意义上的引⽤(reference,&)很相 似,为了更好地区分它们俩,传统意义上的引⽤⼜被称为左值引⽤(lvalue reference)。右值引⽤通常⽤于函数的参数声明⾥。

左值引⽤和右值引⽤的绑定规则:

(1)⾮const左值引⽤只能绑定到⾮const左值;

(2)const左值引⽤可绑定到const左值、⾮const左值、const右值、⾮const右 值;

(3)⾮const右值引⽤只能绑定到⾮const右值;

(4)const右值引⽤可绑定到const右值和⾮const右值。

右值引⽤的其中⼀个场景:右值引⽤的移动构造,移动构造函数和移动赋值运算符的出现,使得资源的所有权可以从⼀个对象转移到 另⼀个对象,⽽⽆需进⾏深拷⻉,从⽽⼤⼤提⾼了程序的运⾏效率。

注意:

 1.右值引⽤,是延⻓了对象的⽣命周期。右值引⽤是⼀个持久的变量,它所引⽤的对象不会在本该 被销毁的时候销毁。

2.在移动构造函数和移动赋值运算符中,要确保源对象在资源转移后处于有效但未指定的状态,⼀ 般做法是将源对象的指针置为 nullptr 。

完美转发是右值引⽤的另⼀个重要应⽤场景,主要用于泛型编程。它能够在函数模板中保持参数的原始值类别(左值或 右值)。这主要通过通⽤引⽤(也叫转发引⽤)来实现。 需要注意的是类模板或函数模板中的&&,不代表右值引⽤,⽽是万能引⽤(其既能接收左值,也能 接收右值(万能))。

void test(int&& temp)
{cout << temp << endl;}int main()
{test(44);return 0;
}
class stu
{
public:string name;int age;stu(string name, int age){this->name = name;this->age = age;cout << "普通构造函数" << endl;}stu(const stu& temp){this->name = temp.name + "ok";this->age = 0;cout << "拷贝构造函数" << endl;}stu(stu&& temp){cout << "移动构造函数" << endl;}};stu test()
{return stu("kk", 44);
}int main()
{stu s1("laoguo", 12);stu s2(s1);stu s3 = test();int b = 33;int&& c =std::move( b);//如果希望将右值引用绑定左值上 需要借助move函数来实现/*int a = 3;//a就是左值,因为可以对a进行赋值或取地址   3这个值它就是右值int& b = a;//左值引用int&& c = 33;//给33起了一个别名叫cint cc = 15;//int&& k = cc;无法将右值引用绑定到左值上int&& pp = a + cc;//因为a+Cc计算后会产生临时变量来存放两者的结果。*/return 0;
}

11、线程类

std::thread为C++11的线程类,使⽤⽅法和boost接⼝⼀样,⾮常⽅便,同时, C++11的std::thread解决了boost::thread中构成参数限制的问题.,具体参考⼴泛⽂ 档。


void task1(int n)
{for (int i = 0; i <n; i++){cout << "#################" << endl;Sleep(1000);}}void task2(int n)
{for (int i = 0; i < n; i++){cout << "$$$$$$$$$$$" << endl;Sleep(1000);}}int main()
{thread thread1(task1, 10);thread thread2(task2, 10);thread1.join();thread2.join();return 0;
}

三、标准模板库( STL简介)

STL(StandardTemplate Library)即标准模板库,是一个具有工业强度的高效的C++程序库。
主要集成了常用的数据结构(类模板实现)和算法(函数实现)
STL的一个重要特点是数据结构和算法的分离
它不是面向对象的,STL主要依赖于模板而不是封装,继承和虚函数(多态性)


C ++STU一共提供了六大组件,包括容器,算法,迭代器,仿函数,配接器和配置器,彼此可以组合套用。

1、容器(Containers)

容器是⽤来管理某⼀类对象的集合,是⼀种数据结构。 C++ 提供了各种不同类型的容器,⽐如 deque、list、vector、map 等。 容器主要分为两⼤类:序列容器和关联容器 序列容器就是将⼀组具有相同类型的对象,以严格的线性形式组织在⼀起。序列 容器可以视为数组和链表的推⼴;STL中的序列容器有3种:vector(动态数组实 现),deque(双向队列), List(双向链表)等。

关联式容器(Associated containers),元素位置取决于特定的排序准则,和插⼊顺序⽆关,set、multiset、map、multimap等。 需要注意的是容器类⾃动申请和释放内存,⽆需new和delete操作。

C++ STL中最基本以及最常⽤的类或容器⽆⾮就是以下⼏个:

string

vector

set

list

map

2、算法(Algorithms)

算法作⽤于容器,它们提供了执⾏各种操作的⽅式,包括对容器内容执⾏初始 化、排序、搜索和转换等操作。算法部分主要由头⽂件, 和组成。 每个容器都有专属的迭代器,⽽算法通过迭代器对容器中 的元素进⾏操作。

3、迭代器(iterators)

迭代器通过迭代器可以在不了解容器内部原理的情况下遍历容器,算法不直接操作容器 中的数据,⽽是通过迭代器间接操作,每⼀个容器都定义了其本身所专有的迭代 器,⽤以存取容器中的元素。本质就是一个类。

4、仿函数

从实现的⻆度看,仿函数是⼀种重载了 operator() 的类或者类模板。 可以帮助算法实现不同的策略。仿函数⼜叫函数对象,是⼀个定义了operator()的对象。你 可以将仿函数视为⼀般函数,只不过不是将所有语句放在函数体⾥,⽽是放在operator()中编 写。

5、配接器

⼀种⽤来修饰容器或者仿函数或迭代器接⼝的东⻄。

6、配置器

负责空间配置与管理,从实现的⻆度讲,配置器是⼀个实现了动态空间配 置、空 间管理,空间释放的类模板。

四、序列容器之vector

向量(vector)是⼀个封装了动态⼤⼩数组的顺序容器(Sequence Container)。跟任意其它类型容器⼀样,它能够存放各种类型的对象。⼀个容器 中的对象必须是同⼀种类型. 优点:尾部添加或移除元素⾮常快速。但是在中部或头部安插元素⽐较费时。

vector的基本操作如下:

1)引⼊vector 使⽤vectpr时需要包先含头⽂件 : #include <vector>

vector属于std命名域,因此需要通过命名限定, 例如:std::vector v; 建议使⽤全局命名域的⽅式:using namespace std;

2)vector成员函数介绍

int main()
{//1.创建vector对象vector<int> vec1;vector<int>vec2(3);vector<int>vec3(3,2);vector<int>vec4(vec1);//2.添加元素 const_iterator begin() const noexcept;//vec1.insert(vec1.begin(),10);//指定位置插入//vec1.insert(vec1.begin(), 11);//vec1.insert(vec1.begin(), 12);//vec1.insert(vec1.begin(), 13);//vec1.insert(vec1.begin() + 3, 55);vec1.insert(vec1.end(), 33);//end()返回容器的末尾位置 begin()返回容器的开头位置vec1.insert(vec1.end(), 44);vec1.push_back(66);//末尾添加vec1.push_back(77);vec1.push_back(88);//3.遍历容器//cout << vec1.size() << endl;for (int i = 0; i < vec1.size(); i++){// cout << vec1[i]<<":" << vec1.at(i) << endl;cout << vec1[i] << endl;}//4.删除容器中的元素//vec1.erase(vec1.begin());//指定位置进行删除//批量删除// vec1.erase(vec1.begin() + 1, vec1.begin()+4);//前闭后开的区间vec1.pop_back();//尾部元素删除// vec1.clear();//全部删除cout << "$$$$$$$$$$$$$$$$$$" << endl;for (int i = 0; i < vec1.size(); i++){cout << vec1[i] << endl;}cout << "$$$$$$$$$$$$$$$$$$" << endl;//6.通过迭代器来遍历元素/*  vector<int>::iterator iter;for (iter=vec1.begin();iter!=vec1.end();iter++){*iter = *iter + 1;cout << *iter << endl;}*///vector<int>::const_iterator iter; 如果在遍历时 不希望修改容器中的元素,可以使用常迭代器类//for (iter = vec1.cbegin(); iter != vec1.cend(); iter++)//{//    //*iter = *iter + 1;//    cout << *iter << endl;//}//反着遍历vector<int> ::const_reverse_iterator iter;for (iter = vec1.rbegin(); iter != vec1.rend(); iter++){//*iter = *iter + 1;cout << *iter << endl;}return 0;
}

http://www.dtcms.com/a/271577.html

相关文章:

  • Spring核心注解揭秘:`@Configuration`与`@Component`的本质区别
  • Windows宿主机 与 VMWare centos虚拟机 之间的通信访问
  • Java异步编程全解析:从基础到高阶实战
  • Shader面试题100道之(41-60)
  • 借助ssh实现web服务的安全验证
  • claude code调用(免费白嫖100额度)
  • CentOS/RHEL LVM 磁盘扩展完整教程
  • 数学模型:十大距离
  • 小程序软装: 组件库开发
  • 打造企业级数据治理运营体系:从项目到产品,再到体系化运营
  • 图像处理中的直方图均衡化:原理与实现
  • 一天两道力扣(3)
  • 减少空间占用的生成模型实战与推理资源消耗量化对比
  • CTFHub————Web[信息泄露(目录遍历、PHPINFO)]
  • Windows Subsystem for Linux (WSL):现代开发的终极跨平台方案
  • 【Modern C++ Part7】_创建对象时使用()和{}的区别
  • 计算机嵌入式基础
  • SpringCache整合SpringBoot使用
  • 洛谷P1044 栈(学习向)
  • Unity Demo-3DFarm详解-其一
  • TCP协议格式与连接释放
  • 智能Agent场景实战指南 Day 8:销售助手Agent开发实战
  • 25春云曦期末考复现
  • “上下文工程”领域的部分参考资料
  • vue中v-for与v-if的优先级
  • 在已有 Nexus3 的基础上搭建 Docker 私有镜像仓库
  • 如何降低AIGC的有效策略是什么?降AIGC工具的创新与应用前景
  • 如何识别SQL Server中需要添加索引的查询
  • 3 STM32单片机-delay延时驱动
  • langchain从入门到精通(四十)——函数调用技巧与流程