CppPrimer笔记 Chapter10 泛型算法
标签: Cpp
概述(10.1)
find(vec.it1,vec.it2,val);
在 [it1,it2) 中寻找 val ,找到则返回指向的容器,没找到则返回it2
- 算法永远不会执行容器操作,即添加,删除元素.其值运行于迭代器上.利用一般的迭代器,可以改变容器中的值,移动元素.利用特殊的迭代器
插入器
可以进行插入操作,但这时给这类迭代器赋值时迭代器自己进行的,而不是算法进行的.
初识泛型算法(10.2)
accumulate(v.cbegin(),v.cend(),0)
第三个参参数作为求和起点,隐含着序列中元素与这个参数可以相加equal(roster1.cbegin(),roster1.cend(),roster2.cbegin())
判断roster1
是否与roster2
的前roster1.size()
个相等,隐含了第二个序列至少与第一个一样长back_inserter
接受一个指向容器的引用,返回一个与该容器绑定的插入迭代器,向该迭代器赋值即调用push_back
将一个具有给定值的元素添加到容器中- 常用函数示例
vector<int> vec;
fill_n(back_inserter(vec), 15, 1);//添加15个1到vec
fill_n(vec.begin(), 5, 0);//将vec前5个换为0
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto ret = copy(begin(arr), end(arr), vec.begin());//将arr值拷贝到vec中
//vec = {0,1,2,3,4,5,6,7,8,9,1,1,1,1,1}
if (ret == vec.end()){ cout << "re == vec.end" << endl; }//true
replace(vec.begin(), vec.end(), 1, 10);//将vec中1换成10
//vec = {0,10,2,3,4,5,6,7,8,9,10,10,10,10,10}
vector<int> vec2;
replace_copy(vec.cbegin(), vec.cend(), back_inserter(vec2), 10, 1);//将vec中10换成1后赋值给vec2,而原vec不变
- 利用
sort
与unique
排序后删去重复元素
void elimDups(vector<string> &words)
{
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
}
向算法传递函数(10.3.1)
stable_sort(words.begin(), words.end(), isShorter);
按照isShorter()
规定的规则来排序,同时stable_sort
保持相等元素的原有顺序- 上行代码中
isShorter
是一个谓词,需满足严格弱序
lambda表达式(10.3.2-10.3.3)
lambda
表达式格式[capture list](parameter list) -> return type{function body}
表示一个可调用的代码单元,我们可以将其理解为一个未命名的内联函数- lambda不能有默认参数
lambda包含
return
之外的任何语句,则编译器假定此lambda返回void
定义lambda时,生成一个与lambda对应的新的未命名类类型.默认情况下,生成的类都包含一个所捕获变量的数据成员,在lambda对象创建时被初始化(而不像函数一样,在调用时拷贝)
- 尤其注意引用拷贝时引用,指针,迭代器的有效性
- 使用
mutable
使得按值捕获的lambda表达式可以修改被捕获变量的值
参数绑定(10.3.4)
- 利用
using std::placeholders
来使用_n
进行形参占位 auto newCallable = bind(callable,arg_list);
来进行绑定,利用_n
进行形参占位,从而被占位的形参达到像变量捕获的效果auto g = bind(f,a,b,_2,c,_1)
回想g(arg1,arg2)
映射为f(a,b,arg2,c,arg1)`- youyu bild那些非占位符参数被拷贝到bind返回的可调用对象中,因而若要按引用传递,则必须使用
ref()
如bind(print,ref(os),_1)
迭代器(10.4)
- 插入迭代器
vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto iter = vec.begin() + 5;//*iter = 6
auto it_in = inserter(vec, iter);
*it_in = 20;
//vec = {1 2 3 4 5 20 6 7 8 9 10}
//*iter;//error 参见 顺序容器 插入后迭代器的有效性问题
*it_in = 30;
//vec = {1 2 3 4 5 20 6 7 8 9 10}
list<int> lst = { 1, 2, 3, 4 };
list<int> lst2, lst3;
copy(lst.cbegin(), lst.cend(), front_inserter(lst2));
//lst2 = {4,3,2,1}
- 流迭代器:被绑定到输入或输出流上,可用来便利所关联的IO流
- 在第一次解引用迭代器时才真正读取
istream_iterator
默认初始化,可以当做尾后值使用- 不支持递减运算
//将in_iter绑定在cin上,其为指向输入流数据的一个容器
//eof默认初始化,可以当做尾后值使用
istream_iterator<int> in_iter(cin),eof;
while(in_iter != eof)
//先解引用,然后指向下一个数字
vec.push_back(*in_iter++);
vector<int> vec2{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
ostream_iterator<int> out_iter(cout, " ");
for (auto e:vec2)
{
*out_iter++ = e;
}
cout << " :out" << endl;
//输出 1 2 3 4 5 6 7 8 9 10 :out
- 反向迭代器
sort(vec.rbegin(),vec.rend());
将最小元素放在vec的末尾
- 移动迭代器P480
5类迭代器(10.5.1)
- 输入迭代器
- 输出迭代器
- 前向迭代器
- 双向迭代器
- 随机访问迭代器
特定容器算法(10.6)
- 链表特有的操作会改变容器