我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++primer超详细讲解泛型算法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++primer超详细讲解泛型算法

初识泛型算法

只读算法

只读取输入范围内的函数,不改变元素,find,accumula也是如此

(1)accumulate算法为求和算法,前两个参数指出求和元素范围,第三个是和的初值,例:

int sum=accumulate(v.begin(),v.end(),0)

(2)操作两个序列的算法

equal算法,确定两个序列是否保存相同的值,将第一个序列的每个元素和第二个序列中的每个元素进行比较,若相同返回true,否则返回false,接受三个参数,前两个表示第一个序列的元素范围,第三个表示第二个序列的首元素

equal(r1.begin(),r1.end(),r2.begin())

写容器算法

(1)拷贝算法

向另一个目的位置迭代器指向的输出序列中的元素写入数据算法。此算法接受三个迭代器,前两个表示一个舒服范围,第三个表示目的序列的起始位置。copy返回目的迭代器的值。

int a1[] = { 0,1,2,3,4,5 };
int a2[sizeof(a1) / sizeof(*a1)];
auto ret = copy(begin(a1), end(a1), a2);

定制操作

lambda表达式

(1)定义

一个lambda表达式表示一个可调用的代码单元,可理解为未命名的内联函数

lambda表达式形式:

[capture list](parameter list) - > return type{function body}

可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体

auto f =[] {return 42}

调用: cout<<f()<<endl;

(2)向lambda传递参数

实参被用来初始化lambda的形参,lambda不能有默认参数

例:

//[](const string &a,const string &b){return a.size()<b.size()}
//调用
sort(w.begin(),w.end(),[](const string &a,const string &b){return a.size()<b.size()})

(3)使用捕获列表

一个lambda通过将局部变量包含在其捕获列表中指出将会使用这些变量,捕获列表指引lambda在其内部包含访问局部变量所需的全部信息

例如,找出第一个大于等于给定长度的单词。

函数biggies实现

void biggies(vector<string> &words,vector<string>::size_type sz)
{
    auto wc=find_if(words.begin(),words.end(),
                    [sz](const string &a){return a.size()>=sz});
}

lambda捕获和返回

(1)值捕获

与传值参数类似,采用值捕获的前提是变量可以拷贝,与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝

void fcun()
{
    size_t v1=42;
    auto f=[v1]{return v1;};
    v1=0;
    auto j=f();
}

由于被捕获变量的值是在lambda创建时拷贝,因此随后对其修改不会影响到lambda内对应的值,上述中j的值为42

(2)引用捕获

void fcun()
{
    size_t v1=42;
    auto f=[&v1]{return v1;};
    v1=0;
    auto j=f();   //j为0,f2保存v1的引用,而非拷贝
}

(3)隐式捕获

可以让编译器根据lambda体中的代码推断我们要使用哪些变量,此时应在捕获列表中写一个&或=,&表示采用捕获引用,=表示采用值捕获方式。

wc=find_if(w.begin(),w.end(),[=](const string &s){return s.size>=sz;});

(4)可变lambda

在值拷贝的情况下,lambda不会改变其值,若希望能够改变被捕获的变量的值,则在参数列表首加上mutable关键字。

void func()
{
    size_t v1=42;
    auto f=[vi]() mutable{return ++v1;};
    v1=0;
    auto j=f();
}

一个引用捕获的变量能否可以修改依赖于此引用指向的是一个const还是非const类型

void fc()
{
	const size_t v1 = 42;
	auto f = [&v1]() mutable {return ++v1; };//无法修改v1
	auto j = f();
	cout << j << endl;
}

(5)指定lambda的返回类型

默认情况下,如果一个lambda体中包含return之外的任何语句,则编译器假定此lambda返回void。

例如:将一个序列中负数替换为其绝对值

transform(v.begin(),v.end(),v.begin(),[](int i){return i<0?-i:i;})

transform接受三个参数,前两个表示迭代器输入序列,第三个表示迭代器目的位置。

上述中,我们无需指定返回类型,因此可以根据条件运算符的类型推断出来。

若改写成存在if语句,则存在错误

transform(v.begin(),v.end(),v.begin(),[](int i){if(i<0) return -i; else return i;})

编译器发现存在return之外的语句,所以推断其返回类型为void,而他却返回了一个int

正确写法:

transform(v.begin(),v.end(),v.begin(),
                [](int i) ->int {if(i<0) return -i; else return i;})

再探迭代器

标准库头文件iterator中还定义了额外几种迭代器,包括如下:

  • 插入迭代器:绑定到一个容器上,向容器插入元素
  • 流迭代器:绑定到输入输出流上,可以用来遍历所关联的IO流
  • 反向迭代器:这些迭代器向后而不是向前移动,forwar_list不存在此迭代器
  • 移动迭代器:移动元素专用

插入迭代器

例:

list<int> lst = { 1,2,3,4 };
list<int> lst2, lst3;
copy(lst.begin(), lst.end(), front_inserter(lst2));
copy(lst.begin(), lst.end(), inserter(lst3, lst3.begin()));

front_inserter总是插入容器的第一个元素之前,所以lst2中的元素顺序为4,3,2,1,而lst3中的元素顺序为1,2,3,4

iostream迭代器

istream_iterator读取输入流,ostream_iterator向一个输出流写数据。

(1)istream_iterator操作

创建流迭代器时,必须指定迭代器将要读写的对象类型,可以创建空的初始化迭代器,用作尾后值使用的迭代器,一旦关联的流遇到文件尾或者IO错误,迭代器的值就与尾后迭代器相等。

例:读取输入数据保存到vector中

vector<int> v;
istream_iterator<int> it(cin);
istream_iterator<int> e;
while (it != e)
    v.push_back(*it++);   //或 v.push_back(it,e)

(2)使用算法操作流迭代器

例:

istream_iterator<int> it(cin);
istream_iterator<int> e;
cout << accumulate(it, e, 0) << endl;

(3)ostream_iterator操作

创建一个ostream_iterator时,可以提供第二参数,他是一个字符串,在输出每个元素后都会打印此字符串,不允许空的或表示尾后的ostream_iterator

vector<int> v = { 1,2,3,4 };
ostream_iterator<int> out(cout, "@@");
for (auto e : v)
	*out++ = e;  //赋值语句实际上是将元素写到cout,且*和++并不做任何事
cout << endl;

反向迭代器

反向迭代器就是在容器中尾元素向首元素反向移动的迭代器,递增一个反向迭代器会向前移动一个元素,递减一个迭代器会向后移动一个元素

将反向迭代器转换为普通迭代器可使用reverse_iterator中的base成员函数来完成转换

例:输出最后一个单词

string line = { "first,middle,last" };
auto r = find(line.rbegin(), line.rend(), ',');
cout << string(r.base(), line.end()) << endl;

到此这篇关于C++ primer超详细讲解泛型算法的文章就介绍到这了,更多相关C++ primer泛型算法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++primer超详细讲解泛型算法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++BoostAlgorithm算法超详细精讲

Boost.Algorithm提供了补充标准库算法的算法。与Boost.Range不同,Boost.Algorithm没有引入新概念。Boost.Algorithm定义的算法类似于标准库中的算法
2022-11-13

C++BoostGraph算法超详细精讲

这篇文章主要介绍了C++BoostGraph算法,我门尝试使用Boost.Graph库来运行Goldberg的最大流算法。Boost.Graph将其称为push_relabel_max_flow
2022-11-13

C++ Boost CircularBuffer算法超详细精讲

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

React diff算法超详细讲解

渲染真实DOM的开销很大,有时候我们修改了某个数据,直接渲染到真实dom上会引起整个dom树的重绘和重排。我们希望只更新我们修改的那一小块dom,而不是整个dom,diff算法就帮我们实现了这点。diff算法的本质就是:找出两个对象之间的差异,目的是尽可能做到节点复用
2022-11-13

C++BoostUtility超详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-12-08

C++BoostUuid超详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-12-08

VueMVVM模型超详细讲解

MVVM是Model-View-ViewModel的缩写,MVVM是一种设计思想,这篇文章主要介绍了Vue生命周期和MVVM框架,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2022-11-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录