这篇文章,虽然叫做STL算法,但准确来说,应该叫STL适配器,不过用法仍与算法差不多,而且部分操作仍是算法的一部分,因此仍然叫做STL算法。该文章中有些函数或类已经在最新C++版本中已被弃用或移除,但仍具有参考价值,因此本文中未删减,关于后续型版本的STL新算法与新类,会推出后续版本补充。
请观看原博客:STL算法(下)
已排序相关操作
集合相关操作
因为set
容器本就具有这些算法应有的特性,所以这里使用vector
模拟集合,并且这些vector
的元素是已排序且无相等元素的。
includes
用法:includes(first1, last1, first2, last2)
或includes(first1, last1, first2, last2, comp)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2>
bool includes(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2);
template <class InputIterator1, class InputIterator2,
class StrictWeakOrdering>
bool includes(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
StrictWeakOrdering comp);
该函数可以测试一个集合是不是另一个集合的子集合,即
S
1
⊆
S
2
S_1 \subseteq S_2
S1⊆S2 也就是说,当且仅当[first1, last1)
中每个元素在[first2, last2)
中存在等价元素,则返回true
该函数与所有其他算法一样,拥有两个版本,第一版本采用operator<
进行比较,第二版本采用comp
进行比较。
复杂度:至多执行2((last1-first1)+(last2-first2))-1
次比较
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int> vec2 = {3, 4, 5, 6, 7};
vector<int> vec3 = {0, 1, 2, 3, 4};
cout << boolalpha << includes(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()) << endl;
cout << boolalpha << includes(vec1.begin(), vec1.end(), vec3.begin(), vec3.end()) << endl;
return 0;
}
输出:
true
false
set_union
用法:set_union(first1, last1, first2, last2, result)
或set_union(first1, last1, first2, last2, result, comp)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2,
class OutputIterator>
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
template <class InputIterator1, class InputIterator2,
class OutputIterator, class StrictWeakOrdering>
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, StrictWeakOrdering comp);
该算法能创建出两个集合的并集,即 S 1 ∪ S 2 S_1 \cup S_2 S1∪S2,该集合内含两个集合的每一个不等价元素,返回值为输出迭代器的尾端。如果在两个集合出现等价元素,那么在输出集合中该元素肯定来自第一个集合。
同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用operator<
进行比较,第二个版本使用comp
进行比较。
复杂度:至多执行2((last1-first1)+(last2-first2))-1
次比较
例子:
int main() {
vector<int> vec1 = {3, 4, 5, 6, 7};
vector<int> vec2 = {0, 1, 2, 3, 4};
vector<int> vec3(10);
auto la = set_union(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
for(auto it = vec3.begin(); it != la; ++it)
cout << *it << " ";
return 0;
}
输出:
0 1 2 3 4 5 6 7
set_intersection
用法:set_intersection(first1, last1, first2, last2, result)
或set_intersection(first1, last1, first2, last2, result, comp)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2,
class OutputIterator>
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
template <class InputIterator1, class InputIterator2,
class OutputIterator, class StrictWeakOrdering>
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, StrictWeakOrdering comp);
该算法能创建出两个集合的交集,即 S 1 ∩ S 2 S_1 \cap S_2 S1∩S2,该集合内含两个集合的每一个等价元素,返回值为输出迭代器的尾端。这些元素都来自第一个集合。
同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用operator<
进行比较,第二个版本使用comp
进行比较。
复杂度:至多执行2((last1-first1)+(last2-first2))-1
次比较
例子:
int main() {
vector<int> vec1 = {3, 4, 5, 6, 7};
vector<int> vec2 = {0, 1, 2, 3, 4};
vector<int> vec3(10);
auto la = set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
for(auto it = vec3.begin(); it != la; ++it)
cout << *it << " ";
return 0;
}
输出:
3 4
set_difference
用法:set_difference(first1, last1, first2, last2, result)
或set_difference(first1, last1, first2, last2, result, comp)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2,
class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
template <class InputIterator1, class InputIterator2,
class OutputIterator, class StrictWeakOrdering>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, StrictWeakOrdering comp);
该算法能创建出两个集合的两集合之差,即s1
对s2
的补集,
S
1
−
S
2
S_1 - S_2
S1−S2,返回值为输出迭代器的尾端。
同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用operator<
进行比较,第二个版本使用comp
进行比较。
复杂度:至多执行2((last1-first1)+(last2-first2))-1
次比较
例子:
int main() {
vector<int> vec1 = {3, 4, 5, 6, 7};
vector<int> vec2 = {0, 1, 2, 3, 4};
vector<int> vec3(10);
auto la = set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
for(auto it = vec3.begin(); it != la; ++it)
cout << *it << " ";
return 0;
}
输出:
5 6 7
set_symmetric_difference
用法:set_symmetric_difference(first1, last1, first2, last2, result)
或set_symmetric_difference(first1, last1, first2, last2, result, comp)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2,
class OutputIterator>
OutputIterator
set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
template <class InputIterator1, class InputIterator2,
class OutputIterator, class StrictWeakOrdering>
OutputIterator
set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, StrictWeakOrdering comp);
该算法能创建出两个集合的对称差,即 ( S 1 − S 2 ) ∪ ( S 2 − S 1 ) (S_1 - S_2) \cup (S_2 - S_1) (S1−S2)∪(S2−S1),返回值为输出迭代器的尾端。
同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用operator<
进行比较,第二个版本使用comp
进行比较。
复杂度:至多执行2((last1-first1)+(last2-first2))-1
次比较
例子:
int main() {
vector<int> vec1 = {3, 4, 5, 6, 7};
vector<int> vec2 = {0, 1, 2, 3, 4};
vector<int> vec3(10);
auto la = set_symmetric_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
for(auto it = vec3.begin(); it != la; ++it)
cout << *it << " ";
return 0;
}
输出:
0 1 2 5 6 7
堆相关操作
关于堆的相关定义与规则这里不再多赘述,请自行观看数据结构相关章节
make_heap
用法:make_heap(first, last)
或make_heap(first, last, comp)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void make_heap(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void make_heap(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering comp);
该函数可以将任意一个区间转换成一个堆
该函数有两个版本,差别在于如何定义某个元素小于另一个元素,第一个版本使用operator<
,第二个版本使用comp
。
复杂度:O(logn)
,最多执行log(last - first)
次比较。
例子:
int main() {
vector<int> vec = {1, 4, 7, 2, 5, 8, 3, 6, 9};
make_heap(vec.begin(), vec.end());
// 自己实现的树形输出
testPrint(vec);
return 0;
}
输出:
9
/ \
6 8
/ \ / \
4 5 7 3
/ \
1 2
push_heap
用法:push_heap(first, last)
或push_heap(first, last, comp)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void push_heap(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void push_heap(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering comp);
该算法可以为堆增加新元素,但接口有点特别,原堆以[first, last-1)
表示,而新增元素为*(last-1)
该函数有两个版本,差别在于如何定义某个元素小于另一个元素,第一个版本使用operator<
,第二个版本使用comp
。
复杂度:O(logn)
,最多执行log(last - first)
次比较。
例子:
int main() {
vector<int> vec = {1, 4, 7, 2, 5, 8, 3, 6, 9};
make_heap(vec.begin(), vec.end());
vec.push_back(16);
push_heap(vec.begin(), vec.end());
testPrint(vec);
return 0;
}
输出:
16
/ \
9 8
/ \ / \
4 6 7 3
/ \ /
1 2 5
pop_heap
用法:pop_heap(first, last)
或pop_heap(first, last, comp)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void pop_heap(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void pop_heap(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering comp);
该函数可以移除堆[first, last)
的最大元素,即将*first
移至last-1
,而[first, last-1)
仍然是一个堆,*(last-1)
则是被移除元素,如果持续调用该函数,则会得到一个已排序数组。
该函数有两个版本,差别在于如何定义某个元素小于另一个元素,第一个版本使用operator<
,第二个版本使用comp
。
复杂度:O(logn)
,最多执行log(last - first)
次比较。
例子:
int main() {
vector<int> vec = {1, 4, 7, 2, 5, 8, 3, 6, 9};
make_heap(vec.begin(), vec.end());
pop_heap(vec.begin(), vec.end());
testPrint(vec, vec.begin() - vec.end() - 1);
cout << "被移除元素:" << *(vec.end()-1);
return 0;
}
输出:
8
/ \
6 7
/ \ / \
4 5 2 3
/
1
被移除元素:9
sort_heap
用法:sort_heap(first, last)
或sort_heap(first, last, comp)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering comp);
该函数会将一个堆转化为一个已排序区间,他不是一个稳定的排序算法,即不会保持元素的相对位置
该函数有两个版本,差别在于如何定义某个元素小于另一个元素,第一个版本使用operator<
,第二个版本使用comp
。
复杂度:最多执行n log(n)
次比较。
例子:
int main() {
vector<int> vec = {1, 4, 7, 2, 5, 8, 3, 6, 9};
make_heap(vec.begin(), vec.end());
sort_heap(vec.begin(), vec.end());
for(auto x : vec)
cout << x << " ";
return 0;
}
输出:
1 2 3 4 5 6 7 8 9
is_heap
用法:is_heap(first, last)
或is_heap(first, last, comp)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void is_heap(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void is_heap(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering comp);
如果区间[first, last)
是一个堆,则该算法会返回true
,否则返回false
该函数有两个版本,差别在于如何定义某个元素小于另一个元素,第一个版本使用operator<
,第二个版本使用comp
。
复杂度:O(n)
,最多执行(last-first)-1
次比较
例子:
int main() {
vector<int> vec = {1, 4, 7, 2, 5, 8, 3, 6, 9};
cout << boolalpha << is_heap(vec.begin(), vec.end()) << endl;
make_heap(vec.begin(), vec.end());
cout << boolalpha << is_heap(vec.begin(), vec.end()) << endl;
return 0;
}
输出:
false
true
迭代器类
问题来了,既然容器自己带有迭代器,为什么我们还要定义一个外部迭代器来使用呢?原因在于内部迭代器和外部迭代器的行为不同,如果说i
是一个list
容器的头迭代器,我们对其赋值,该迭代器具有覆盖语义,使用会将原元素覆盖替换为将要的元素,而front_insert_iterator
则具有安插含义,会将想插入的元素安插在头元素之前,而非覆盖原有元素。
Insert Iterator
front_insert_iterator
类定义:front_insert_iterator<FrontInsertiobSequence>
构造函数:
// constructor
front_insert_iterator(FrontInertionSequence& s);
// copy constructor
front_insert_iterator(const front_insert_iterator&);
定义头文件:<iterator>
该类是具有输出迭代器功能的一个适配器,通过该类可以完成赋值动作,即将要插入的元素安插于容器的第一个元素之前。
例子:
int main() {
list<int> li1 = {1, 2, 3};
list<int> li2 = {4, 5, 6};
front_insert_iterator<list<int>> fi_iter(li1);
*fi_iter++ = 10;
for(auto x : li1)
cout << x << " ";
cout << endl;
copy(li2.begin(), li2.end(), fi_iter);
for(auto x : li1)
cout << x << " ";
cout << endl;
return 0;
}
输出:
10 1 2 3
6 5 4 10 1 2 3
front_inserter
用法:front_inserter(c)
定义头文件:<iterator>
函数原型:
template <class Container>
front_insert_iterator<Container> front_inserter(Container& c);
该函数是front_insert_iterator
的一个辅助函数,该函数可以利用参数推导出该类型并返回该类型的front_insert_iterator
,这样做会比较方便,使得我们不必精确写出插入迭代器的类型。
例子:
int main() {
list<int> li1 = {1, 2, 3};
list<int> li2 = {4, 5, 6};
copy(li2.begin(), li2.end(), front_inserter(li1));
for(auto x : li1)
cout << x << " ";
cout << endl;
return 0;
}
输出:
6 5 4 1 2 3
back_insert_iterator
类定义:back_insert_iterator<BackInsertiobSequence>
定义头文件:<iterator>
构造函数:
// constructor
back_insert_iterator(BackInertionSequence& s);
// copy constructor
back_insert_iterator(const back_insert_iterator&);
该类是具有输出迭代器功能的一个适配器,通过该类可以完成赋值动作,即将要插入的元素安插于容器的最后一个元素之后。
例子:
int main() {
vector<int> vec1 = {1, 2, 3};
vector<int> vec2 = {4, 5, 6};
back_insert_iterator<vector<int>> bi_iter(vec1);
*bi_iter++ = 10;
for(auto x : vec1)
cout << x << " ";
cout << endl;
copy(vec2.begin(), vec2.end(), bi_iter);
for(auto x : vec1)
cout << x << " ";
cout << endl;
return 0;
}
输出:
1 2 3 10
1 2 3 10 4 5 6
back_inserter
用法:back_inserter(c)
定义头文件:<iterator>
函数原型:
template <class Container>
back_insert_iterator<Container> back_inserter(Container& c);
该函数是back_insert_iterator
的一个辅助函数,该函数可以利用参数推导出该类型并返回该类型的back_insert_iterator
,这样做会比较方便,使得我们不必精确写出插入迭代器的类型。
例子:
int main() {
vector<int> vec1 = {1, 2, 3};
vector<int> vec2 = {4, 5, 6};
copy(vec2.begin(), vec2.end(), back_inserter(vec1));
for(auto x : vec1)
cout << x << " ";
cout << endl;
return 0;
}
输出:
1 2 3 4 5 6
insert_iterator
类定义:back_insert_iterator<Container>
定义头文件:<iterator>
构造函数:
// constructor
insert_iterator(Container& c, Container::iterator i);
// copy constructor
insert_iterator(const insert_iterator&);
该类是具有输出迭代器功能的一个适配器,通过该类可以完成赋值动作,即将要插入的元素安插于指定的迭代器之前插入元素。值得注意的是,每次插入元素之后,该类都会更新目标迭代器,即该类始终会在某一元素前插入其他的元素,若要实在在某一位置前插入其他元素,建议搭配后续的适配器next
使用。
例子:
int main() {
vector<int> vec1 = {1, 2, 3};
vector<int> vec2 = {4, 5, 6};
insert_iterator<vector<int>> bi_iter(vec1, vec1.begin()+2);
*bi_iter++ = 10;
for(auto x : vec1)
cout << x << " ";
cout << endl;
copy(vec2.begin(), vec2.end(), bi_iter);
for(auto x : vec1)
cout << x << " ";
cout << endl;
return 0;
}
输出:
1 2 10 3
1 2 10 4 5 6 3
inserter
用法:inserter(c, i)
定义头文件:<iterator>
函数原型:
template <class Container>
insert_iterator<Container> back_inserter(Container& c,
typename Container::iterator i);
该函数是insert_iterator
的一个辅助函数,该函数可以利用参数推导出该类型并返回该类型的insert_iterator
,第二个参数的typename
只是为了编译器辨认出Container::iterator
是一个类型,而不是一个类内已声明的变量,详细解答请参考C++模板编程
例子:
int main() {
vector<int> vec1 = {1, 2, 3};
vector<int> vec2 = {4, 5, 6};
copy(vec2.begin(), vec2.end(), inserter(vec1, vec1.begin()+2));
for(auto x : vec1)
cout << x << " ";
cout << endl;
return 0;
}
输出:
1 2 4 5 6 3
Stream Iterator
istream_iterator
类定义:istream_iterator<T, charT, traits, Distance>
定义头文件:<iterator>
构造函数:
// constructor
istream_iterator(istream_type& s);
// default constructor
istream_iterator();
// copy constructor
istream_iterator(const istream_iterator&);
该迭代器是一种输入迭代器,它能为某个输入流执行格式化输入动作,在C++
标准库中,istream
并不是一个类,而是一个typedef
,它是basic_istream<char, char_traits<char>>
的别名,它可以为一般化的字符执行格式化输入
值得注意的是,该类的constructor
会产生一个可从输入流中读取数据的一个迭代器,当该迭代器到达输入流的终点时,这个迭代器会跟end-of-stream
比较的结果会相等,该end-of-stream
可以由default constructor
产生得到。得到的end-of-stream
是最后一位元素的下一位,可以在构造某区间时用上。
例子:
/**
* in.txt中内容为
* 123456
* 654321
* 789456123
*
* 标准输入内容为123 456 789 ^Z
* ^Z 用于截断输入流
*/
int main() {
vector<int> vec;
vector<string> vec_s;
// 该迭代器用于从标准输入流读入int类型数据
istream_iterator<int> is(cin);
istream_iterator<int> eof;
copy(is, eof, back_inserter(vec));
// 该迭代器用于从文件输入流读入string类型数据
ifstream in_file("in.txt");
if(!in_file.is_open())
return -1;
istream_iterator<string> f_is(in_file);
istream_iterator<string> f_eof;
copy(f_is, f_eof, back_inserter(vec_s));
for(auto x : vec)
cout << x << " ";
cout << endl;
for(auto x : vec_s)
cout << x << " ";
cout << endl;
return 0;
}
输出:
123 456 789
123456 654321 789456123
ostream_iterator
类定义:ostream_iterator<T, charT, traits>
定义头文件:<iterator>
构造函数:
// constructor
ostream_iterator(ostream_type& s, const charT* delim);
ostream_iterator(ostream_type& s);
// copy constructor
ostream_iterator(const ostream_iterator&);
该迭代器是一种输出迭代器,它能为将一个可输出对象格式化输出到某个特定的输出流中,同样的,ostream
并不是一个类,它是basic_ostream<char, char_trsits<char>>
的别名。
值得注意的是,它会将可输出对象输出到输出流ostream_type
中,若有参数delim
,则会将delim
作为分隔符输出到输出流中,若没有参数delim
则会以空指针作为分隔符。
例子:
/**
* 输出到其他输出流类似于isream_iterator的实例
*/
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6};
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout));
cout << endl;
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, ","));
return 0;
}
输出:
123456
1,2,3,4,5,6,
istreambuf_iterator
类定义:istreambuf_iterator<charT, traits>
定义头文件:<iterator>
构造函数:
// constructor
istreambuf_iterator(istream_type& s);
istreambuf_iterator(istream_type* s);
// default constructor
istreambuf_iterator();
// copy constructor
istreambuf_iterator(const istreambuf_iterator&);
该迭代器是一种输入迭代器,它与istream_iterator
非常相似,不同的一点在于,它不执行任何类型的格式化输出,而是从输入流中读入单个字符,就像istream_iterator
一样,该类的constructor
会产生一个可从输入流中读取数据的一个迭代器,当该迭代器到达输入流的终点时,这个迭代器会跟end-of-stream
比较的结果会相等,该end-of-stream
可以由default constructor
产生得到。得到的end-of-stream
是最后一位元素的下一位,可以在构造某区间时用上。
该类的最经典用法就是将文件中的字符赋值给string
,肯会有使用ifstream
获取文件内容,任何赋值给string
,这肯定是错误的,因为读取的char*
赋值给string
时遇到\0
便会停止。
该类有两个构造函数,值引用构造函数等价于:初始化迭代器,并存储s.rdbuf()
的值于该类的数据成员,若s.rdbuf()
为空,则构造尾迭代器,值传递构造函数则是初始化迭代器,并存储s
的值于自身数据成员,若s
为空,则构造尾迭代器。
例子:
/**
* in.txt中内容为
* nihao hello hahaha
* shijie world
*/
int main() {
fstream f;
f.open("in.txt", ios::in);
// 只能将单个单词存入string
string s;
while(f >> s)
cout << s << " ";
cout << endl;
f.close();
ifstream in_file("in.txt");
if(!in_file.is_open())
return -1;
istreambuf_iterator<char> f_is(in_file);
istreambuf_iterator<char> f_eof;
// 能将文件所有内容存入string
string str(f_is, f_eof);
cout << str;
return 0;
}
输出:
nihao hello hahaha shijie world
nihao hello hahaha
shijie world
ostreambuf_iterator
类定义:ostreambuf_iterator<charT, traits>
定义头文件:<iterator>
构造函数:
// constructor
ostreambuf_iterator(ostream_type& s);
ostreambuf_iterator(ostream_type* s);
// default constructor
ostreambuf_iterator();
// copy constructor
ostreambuf_iterator(const ostreambuf_iterator&);
该迭代器是一种输出迭代器,它与ostream_iterator
非常相似,不同的一点在于,它会将单字符写入输出流中,但不会执行任何类型的格式化输出。
该类的最经典用法就是将文件中的字符赋值给string
,肯会有使用ifstream
获取文件内容,任何赋值给string
,这肯定是错误的,因为读取的char*
赋值给string
时遇到\0
便会停止。
该类主要配合sstream
等流使用。
例子:
int main() {
ostreambuf_iterator<char> out(cout);
string str("hello\nhahaha\nnihao");
copy(str.begin(), str.end(), out);
return 0;
}
输出:
hello
hahaha
nihao
reverse_iterator
类定义:reverse_iterator<Iterator>
定义头文件:<iterator>
构造函数:
// constructor
reverse_iterator(iterator_type s);
// default constructor
reverse_iterator();
// copy constructor
reverse_iterator(const reverse_iterator&);
reverse_iterator(const reverse_iterator<I>& i);
该迭代器是一种迭代器适配器,能够在区间上逆向移动,给定一个区间[f, l)
,则有[reverse_iterator<Iter>(l), reverse_iterator<Iter>(f))
包含有相同的元素,但次序相反。因为l
指向的是区间的最后一个元素的下一个位置,所以reverse_iterator<Iter>(l)
指向的是*(l-1)
的元素,同样的,其他的迭代器都应该指向前一个位置,此为同一性。
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 正序输出
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// 逆序输出
copy(reverse_iterator<vector<int>::iterator>(vec.end()),
reverse_iterator<vector<int>::iterator>(vec.begin()),
ostream_iterator<int>(cout, " "));
return 0;
}
输出:
1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1
其余迭代器操作
advance
用法:advance(it, n)
定义头文件:<iterator>
函数原型:
template <class InputIterator, class Distance>
void advance(InputIterator& it, Distance n);
该函数可以增加给定迭代器的n
个元素的步长,若n
尾负数,则该迭代器自减,当然,在该情况下需要满足该迭代器是双向迭代器。
复杂度:线性O(n)
,若迭代器是随机访问迭代器,则复杂度可以为O(1)
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto it = vec.begin();
advance(it, 4);
cout << *it;
return 0;
}
输出:
5
distance
用法:advance(first, last)
定义头文件:<iterator>
函数原型:
template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type
advance(InputIterator first, InputIterator last);
该函数可以返回迭代器first
到last
的路程,该迭代器必须可以从first
结果自增到last
,否则函数未定义。若若使用随机访问迭代器且first
可以抵达last
,则返回值可为负数。
复杂度:线性O(n)
,若迭代器是随机访问迭代器,则复杂度可以为O(1)
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << distance(vec.begin(), vec.end());
return 0;
}
输出:
9
next
用法:next(it)
或next(it, 2)
定义头文件:<iterator>
函数原型:
template <class InputIterator>
InputIterator next(InputIterator it,
typename iterator_traits<InputIterator>::difference_type n = 1);
该函数可以返回迭代器it
的第n
个后继元素,若n
不传参默认向后1个元素。
复杂度:线性O(n)
,若迭代器是随机访问迭代器,则复杂度可以为O(1)
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto it = vec.begin();
cout << *next(it, 4) << endl;
cout << *next(it) << endl;
return 0;
}
输出:
5
2
prev
用法:prev(it)
或prev(it, 2)
定义头文件:<iterator>
函数原型:
template <class InputIterator>
InputIterator prev(InputIterator it,
typename iterator_traits<InputIterator>::difference_type n = 1);
该函数可以返回迭代器it
的第n
个前驱元素,若n
不传参默认向前1个元素。
复杂度:线性O(n)
,若迭代器是随机访问迭代器,则复杂度可以为O(1)
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto it = vec.end();
cout << *prev(it, 4) << endl;
cout << *prev(it) << endl;
return 0;
}
输出:
6
9
iterator
类定义:iterator<Category, T, Distance, Pointer, Reference>
类模板:
template <class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator {
typedef Category iterator_category; // 迭代器类型
typedef T value_type; // 数值型别
typedef Pointer pointer; // 数值型别的指针
typedef Reference reference; // 数值型别的引用
typedef Distance difference_type; // 差距型别
};
定义头文件:<iterator>
该类是一个空的类,它里面没有任何成员函数或成员变量,该类可方便用于自主定义迭代器,在STL
里,若迭代器要配合容器,算法和适配器工作,得满足一些条件,详细请看迭代器章节,这些条件我们可以自主定义,当然,也可将该类用作父类,该类的派生类能提供迭代器所需的基本结构。
值得注意的是,该类在C++17
中已被弃用,但该类的实用性还是有的,因此在这里提及。
例子:
// 自己实现的输出迭代器
template <class T>
class my_output_iterator : public iterator<output_iterator_tag, T, ptrdiff_t, T*, T&> {
private:
ostream* os;
const char* str;
public:
my_output_iterator(ostream& s, const char* c = nullptr) : os(&s), str(c) {}
my_output_iterator(const my_output_iterator& i) : os(i.os), str(i.str) {}
my_output_iterator& operator=(const my_output_iterator& i) {
os = i.os;
str = i.str;
return *this;
}
my_output_iterator<T>& operator=(const T& value) {
*os << value;
if(str)
*os << str;
return *this;
}
my_output_iterator<T>& operator*() { return *this; }
my_output_iterator<T>& operator++() { return *this; }
my_output_iterator<T> operator++(int) { return *this; }
};
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
copy(vec.begin(), vec.end(), my_output_iterator<int>(cout, " "));
return 0;
}
输出:
1 2 3 4 5 6 7 8 9
函数对象类
函数对象基类
unary_function
类定义:unary_function<Arg, Result>
类模板:
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type; // 一元参数类型
typedef Result result_type; // 返回类型
};
定义头文件:<functional>
该类与iterator
一样,是一个空的类,它里面没有任何成员函数或成员变量,该类可方便用于自主定义可适配容器,算法,迭代器和适配器的函数对象。该类的派生类能提供一元求函数对象的空的基本结构。
值得注意的是,该类在C++17
中已被弃用,但该类的实用性还是有的,因此在这里提及。
例子:
class doubleValue : public unary_function<double, double> {
public:
double operator()(double x) {
return x * 2;
}
};
int main() {
vector<double> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<double> vec_result;
transform(vec.begin(), vec.end(), back_inserter(vec_result), doubleValue());
copy(vec.begin(), vec.end(), my_output_iterator<double>(cout, " "));
cout << endl;
copy(vec_result.begin(), vec_result.end(), my_output_iterator<double>(cout, " "));
return 0;
}
输出:
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
binary_function
类定义:binary_function<Arg1, Arg2, Result>
类模板:
template <class Arg1, class Arg2, class Result>
struct unary_function {
typedef Arg1 first_argument_type; // 第一参数类型
typedef Arg2 second_argument_type; // 第二参数类型
typedef Result result_type; // 返回类型
};
定义头文件:<functional>
该类与unary_function
一样,是一个空的类,它里面没有任何成员函数或成员变量,该类可方便用于自主定义可适配容器,算法,迭代器和适配器的函数对象。该类的派生类能提供二元求函数对象的空的基本结构。
值得注意的是,该类在C++17
中已被弃用,但该类的实用性还是有的,因此在这里提及。
例子:
class valueDivideValue : public binary_function<double, double, double> {
public:
double operator()(double x, double y) {
return x / y;
}
};
int main() {
vector<double> vec1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<double> vec2 = {9, 8, 7, 6, 5, 4, 3, 2, 1};
vector<double> vec_result;
transform(vec1.begin(), vec1.end(), vec2.begin(), back_inserter(vec_result), valueDivideValue());
copy(vec_result.begin(), vec_result.end(), my_output_iterator<double>(cout, " "));
return 0;
}
输出:
0.111111 0.25 0.428571 0.666667 1 1.5 2.33333 4 9
算术运算
plus
类定义:plus<T>
类模板:
template <class T>
struct plus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const {
return x + y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator+
运算,返回值则为x
与y
的元素之和。
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 4};
vector<int> vec2 = {6, 7, 8, 9};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<int>(cout, " "), plus<int>());
return 0;
}
输出:
7 9 11 13
minus
类定义:minus<T>
类模板:
template <class T>
struct minus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const {
return x - y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator-
运算,返回值则为x
与y
的元素之差。
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 4};
vector<int> vec2 = {9, 8, 7, 6};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<int>(cout, " "), minus<int>());
return 0;
}
输出:
-8 -6 -4 -2
multiplies
类定义:multiplies<T>
类模板:
template <class T>
struct multiplies : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const {
return x * y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator*
运算,返回值则为x
与y
的元素之积。
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 4};
vector<int> vec2 = {9, 8, 7, 6};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<int>(cout, " "), multiplies<int>());
return 0;
}
输出:
9 16 21 24
divides
类定义:divides<T>
类模板:
template <class T>
struct divides : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const {
return x / y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator/
运算,返回值则为x
与y
的元素之商。
例子:
int main() {
vector<double> vec1 = {1, 2, 3, 4};
vector<double> vec2 = {9, 8, 7, 6};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<int>(cout, " "), divides<int>());
return 0;
}
输出:
0.111111 0.25 0.428571 0.666667
modulus
类定义:modulus<T>
类模板:
template <class T>
struct modulus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const {
return x % y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator%
运算,返回值则为x
与y
的元素之模。
例子:
int main() {
vector<int> vec1 = {9, 8, 7, 6};
vector<int> vec2 = {2, 3, 4, 5};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<int>(cout, " "), modulus<int>());
return 0;
}
输出:
1 2 3 1
negate
类定义:negate<T>
类模板:
template <class T>
struct negate : public unary_function<T, T> {
T operator()(const T& x) const {
return -x;
}
};
定义头文件:<functional>
该类是unary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator-
取反运算,返回值则为x
的取反值。
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
transform(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "), negate<int>());
return 0;
}
输出:
-1 -2 -3 -4 -5 -6 -7 -8 -9
大小比较
equal_to
类定义:equal_to<T>
类模板:
template <class T>
struct equal_to : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x == y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator==
运算,返回值则为bool
类型。
例子:
int main() {
vector<int> vec1 = {1, 4, 7, 5};
vector<int> vec2 = {2, 4, 7, 9};
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), equal_to<int>());
return 0;
}
输出:
0 1 1 0
not_equal_to
类定义:not_equal_to<T>
类模板:
template <class T>
struct not_equal_to : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x != y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator!=
运算,返回值则bool
类型。
例子:
int main() {
vector<int> vec1 = {1, 4, 7, 5};
vector<int> vec2 = {2, 4, 7, 9};
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), not_equal_to<int>());
return 0;
}
输出:
1 0 0 1
less
类定义:less<T>
类模板:
template <class T>
struct less : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x < y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator<
运算,返回值则bool
类型。
例子:
int main() {
vector<int> vec = {7, 5, -4, -6, 9, 0, 4};
// 寻找第一个小于5的元素
auto i = find_if(vec.begin(), vec.end(), bind2nd(less<int>(), 5));
cout << *i;
return 0;
}
输出:
-4
greater
类定义:greater<T>
类模板:
template <class T>
struct greater : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x > y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator>
运算,返回值则bool
类型。
例子:
int main() {
vector<int> vec = {7, 5, -4, -6, 9, 0, 4};
// 寻找第一个大于7的元素
auto i = find_if(vec.begin(), vec.end(), bind2nd(greater<int>(), 7));
cout << *i;
return 0;
}
输出:
9
less_equal
类定义:less<T>
类模板:
template <class T>
struct less_equal : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x <= y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator<=
运算,返回值则bool
类型。
例子:
int main() {
vector<int> vec = {7, 5, -4, -6, 9, 0, 4};
// 寻找第一个小于5的元素
auto i = find_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 5));
cout << *i;
return 0;
}
输出:
5
greater_equal
类定义:greater_equal<T>
类模板:
template <class T>
struct greater_equal : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x >= y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator>
运算,返回值则bool
类型。
例子:
int main() {
vector<int> vec = {7, 5, -4, -6, 9, 0, 4};
// 寻找第一个大于等于7的元素
auto i = find_if(vec.begin(), vec.end(), bind2nd(greater_equal<int>(), 7));
cout << *i;
return 0;
}
输出:
7
逻辑运算
logical_and
类定义:logical_and<T>
类模板:
template <class T>
struct logical_and : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x && y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator&&
与运算,返回值则bool
类型。
例子:
int main() {
vector<bool> vec1 = {true, false, false, true};
vector<bool> vec2 = {false, false, true, true};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<bool>(cout, " "), logical_and<bool>());
return 0;
}
输出:
false false false true
logical_or
类定义:logical_or<T>
类模板:
template <class T>
struct logical_or : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x || y;
}
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类要求两个参数的型别相同,且能进行operator||
或运算,返回值则bool
类型。
例子:
int main() {
vector<bool> vec1 = {true, false, false, true};
vector<bool> vec2 = {false, false, true, true};
transform(vec1.begin(), vec1.end(), vec2.begin(),
ostream_iterator<bool>(cout, " "), logical_or<bool>());
return 0;
}
输出:
true false true true
logical_not
类定义:logical_not<T>
类模板:
template <class T>
struct logical_not : public unary_function<T, bool> {
bool operator()(const T& x) const {
return !x;
}
};
定义头文件:<functional>
该类是unary_function
的一个派生类(C++17
之前),该类要求参数能进行operator!
非运算,返回值则bool
类型。
例子:
int main() {
vector<bool> vec = {true, false, false, true};
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), logical_not<bool>());
return 0;
}
输出:
false true true false
成员函数适配器
该适配器用来将各个类的成员函数当作仿函数来搭配其他的容器或算法使用,如果调用的函数是一个虚函数,那么这便是一个多态函数调用,因此该适配器还是面向对象编程与泛型编程之间的桥梁。
mem_fun_t
类定义:mem_fun_t<R, X>
类模板:
template <class R, class X>
struct mem_fun_t : public unary_function<X*, R> {
mem_fun_t(R (X::*f)());
R operator()(X* x) const;
};
定义头文件:<functional>
该类是unary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f()
,那么mem_fun_t<R, X>
便成为一个成员函数适配器,使得可以以一般函数的方式来调用f()
。
在构造该类时需要一个指针,指向X
的成员函数,同样的该适配器需要一个operator()
来使得被算法或容器调用。如果F
使一个mem_fun_t
,是以成员函数X::f()
构造出来的,并且x
是指向该成员函数的函数指针,那么F(x)
等价于x->f()
,两则的差别在于语法层面,F
支持适配于unary_function
的接口。
例子:
struct B {
virtual void print() = 0;
};
struct C1 : public B {
void print() {
cout << "C1" << endl;
}
};
struct C2 : public B {
void print() {
cout << "C2" << endl;
}
};
int main() {
vector<B*> vec;
vec.push_back(new C1);
vec.push_back(new C2);
vec.push_back(new C2);
vec.push_back(new C1);
for_each(vec.begin(), vec.end(), mem_fun_t<void, B>(&B::print));
return 0;
}
输出:
C1
C2
C2
C1
mem_fun1_t
类定义:mem_fun1_t<R, X, A>
类模板:
template <class R, class X, class A>
struct mem_fun1_t : public binary_function<X*, A, R> {
mem_fun1_t(R (X::*f)(A));
R operator()(X* x, A a) const;
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f(A)
,那么mem_fun1_t<R, X, A>
便成为一个成员函数适配器。
同mem_fun_t
一样,不同点在于该类的operator()
接受两个参数,第一参数为X*
,第二个参数为A
。即支持类成员函数可以有一个参数。
例子:
struct Calcu {
virtual double calculate(double) = 0;
};
struct Square : public Calcu {
double calculate(double x) {
return x * x;
}
};
struct Plus : public Calcu {
double calculate(double x) {
return x + x;
}
};
int main() {
vector<Calcu*> operation;
operation.push_back(new Square());
operation.push_back(new Square());
operation.push_back(new Plus());
operation.push_back(new Square());
operation.push_back(new Plus());
vector<double> value = {2, 3, 4, 5, 6};
transform(operation.begin(), operation.end(), value.begin(), ostream_iterator<double>(cout, " "),
mem_fun1_t<double, Calcu, double>(&Calcu::calculate));
return 0;
}
输出:
4 9 8 25 12
const_mem_fun_t
类定义:const_mem_fun_t<R, X>
类模板:
template <class R, class X>
struct const_mem_fun_t : public unary_function<X*, R> {
const_mem_fun_t(R (X::*f)()) const;
R operator()(X* x) const;
};
定义头文件:<functional>
该类是unary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f() const
,那么const_mem_fun_t<R, X>
便成为一个成员函数适配器,使得可以以一般函数的方式来调用f()
。
该函数与mem_fun_t
不同的一点在于该类接受的成员函数是一个通过const
修饰的成员函数。
例子:
struct B {
virtual void print() const = 0;
};
struct C1 : public B {
void print() const {
cout << "C1" << endl;
}
};
struct C2 : public B {
void print() const {
cout << "C2" << endl;
}
};
int main() {
vector<B*> vec;
vec.push_back(new C1);
vec.push_back(new C2);
vec.push_back(new C2);
vec.push_back(new C1);
for_each(vec.begin(), vec.end(), const_mem_fun_t<void, B>(&B::print));
return 0;
}
输出:
C1
C2
C2
C1
const_mem_fun1_t
类定义:const_mem_fun1_t<R, X, A>
类模板:
template <class R, class X, class A>
struct const_mem_fun1_t : public binary_function<X*, A, R> {
const_mem_fun1_t(R (X::*f)(A)) const;
R operator()(X* x, A a) const;
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f(A)
,那么mem_fun1_t<R, X, A>
便成为一个成员函数适配器。
同mem_fun1_t
一样,不同点在于该类的只接受以const
修饰的成员函数。
例子:
struct Calcu {
virtual double calculate(double) const = 0;
};
struct Square : public Calcu {
double calculate(double x) const {
return x * x;
}
};
struct Plus : public Calcu {
double calculate(double x) const {
return x + x;
}
};
int main() {
vector<Calcu*> operation;
operation.push_back(new Square);
operation.push_back(new Plus);
operation.push_back(new Square);
operation.push_back(new Plus);
operation.push_back(new Square);
vector<double> value = {2, 3, 4, 5, 6};
transform(operation.begin(), operation.end(), value.begin(), ostream_iterator<double>(cout, " "),
const_mem_fun1_t<double, Calcu, double>(&Calcu::calculate));
return 0;
}
输出:
4 6 16 10 36
mem_fun
用法:mem_fun(R (X::*f))
定义头文件:<functional>
函数原型:
template<class Res, class X>
std::mem_fun_t<Res, X> mem_fun( Res (X::*f)() );
template<class R, class X>
std::const_mem_fun_t<Res, X> mem_fun( Res (X::*f)() const );
template<class R, class X, class Arg>
std::mem_fun1_t<Res, X, Arg> mem_fun( Res (X::*f)(Arg) );
template<class R, class X, class Arg>
std::const_mem_fun1_t<Res, X, Arg> mem_fun( Res (X::*f)(Arg) const );
该函数是以上四种成员函数适配器的一个辅助函数,该函数可以利用参数推导出该类型并返回其类型。
例子:
struct Calcu {
virtual double calculate(double) = 0;
};
struct Square : public Calcu {
double calculate(double x) {
return x * x;
}
};
struct Plus : public Calcu {
double calculate(double x) {
return x + x;
}
};
struct B {
virtual void print() const = 0;
};
struct C1 : public B {
void print() const {
cout << "C1" << endl;
}
};
struct C2 : public B {
void print() const {
cout << "C2" << endl;
}
};
int main() {
vector<Calcu*> operation;
operation.push_back(new Square);
operation.push_back(new Plus);
operation.push_back(new Plus);
vector<double> value = {2, 3, 4};
vector<B*> vec;
vec.push_back(new C1);
vec.push_back(new C2);
vec.push_back(new C1);
transform(operation.begin(), operation.end(), value.begin(),
ostream_iterator<double>(cout, " "), mem_fun(&Calcu::calculate));
cout << endl;
for_each(vec.begin(), vec.end(), mem_fun(&B::print));
return 0;
}
输出:
4 6 8
C1
C2
C1
mem_fun_ref_t
类定义:mem_fun_ref_t<R, X>
类模板:
template <class R, class X>
struct mem_fun_ref_t : public unary_function<X*, R> {
mem_fun_ref_t(R (X::*f)());
R operator()(X& x) const;
};
定义头文件:<functional>
该类是unary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f()
,那么mem_fun_t<R, X>
便成为一个成员函数适配器,使得可以以一般函数的方式来调用f()
。与mem_fun_t
不同的在于,mem_fun_t
支持operator()
接受一个型别为X*
的参数。该类支持接受一个型别为X&
的参数。
同样的,如果F
使一个mem_fun_ref_t
,是以成员函数X::f()
构造出来的,并且x
是指向该成员函数的函数指针,那么F(x)
等价于x.f()
,两则的差别在于语法层面,F
支持适配于unary_function
的接口。
例子:
struct B {
virtual void print() = 0;
};
struct C1 : public B {
void print() {
cout << "C1" << endl;
}
};
struct C2 : public B {
void print() {
cout << "C2" << endl;
}
};
int main() {
vector<C1> vec; // 要求传入引用
vec.push_back(C1());
vec.push_back(C1());
for_each(vec.begin(), vec.end(), mem_fun_ref_t<void, B>(&B::print));
return 0;
}
输出:
C1
C1
mem_fun1_ref_t
类定义:mem_fun1_ref_t<R, X, A>
类模板:
template <class R, class X, class A>
struct mem_fun1_ref_t : public binary_function<X*, A, R> {
mem_fun1_ref_t(R (X::*f)(A));
R operator()(X& x, A a) const;
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f(A)
,那么mem_fun1_ref_t<R, X, A>
便成为一个成员函数适配器。
同mem_fun1_t
一样,不同点在于该类的operator()
接受两个参数,第一参数为X&
,第二个参数为A
。即支持类成员函数可以有一个参数。
例子:
struct Calcu {
virtual double calculate(double) = 0;
};
struct Square : public Calcu {
double calculate(double x) {
return x * x;
}
};
struct Plus : public Calcu {
double calculate(double x) {
return x + x;
}
};
int main() {
vector<Square> operation;
operation.push_back(Square());
operation.push_back(Square());
operation.push_back(Square());
vector<double> value = {2, 3, 4};
transform(operation.begin(), operation.end(), value.begin(), ostream_iterator<double>(cout, " "),
mem_fun1_ref_t<double, Calcu, double>(&Calcu::calculate));
return 0;
}
输出:
4 9 16
const_mem_fun_ref_t
类定义:const_mem_fun_ref_t<R, X>
类模板:
template <class R, class X>
struct const_mem_fun_ref_t : public unary_function<X*, R> {
const_mem_fun_ref_t(R (X::*f)()) const;
R operator()(X& x) const;
};
定义头文件:<functional>
该类是unary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f()
,那么mem_fun_t<R, X>
便成为一个成员函数适配器,使得可以以一般函数的方式来调用f()
。与const_mem_fun_t
不同的在于,const_mem_fun_t
支持operator()
接受一个型别为X*
的参数。该类支持接受一个型别为X&
的参数。
同样的,该类只接受以const
修饰的类成员函数。
例子:
struct B {
virtual void print() const = 0;
};
struct C1 : public B {
void print() const {
cout << "C1" << endl;
}
};
struct C2 : public B {
void print() const {
cout << "C2" << endl;
}
};
int main() {
vector<C1> vec;
vec.push_back(C1());
vec.push_back(C1());
for_each(vec.begin(), vec.end(), const_mem_fun_ref_t<void, B>(&B::print));
return 0;
}
输出:
C1
C1
const_mem_fun1_ref_t
类定义:const_mem_fun1_ref_t<R, X, A>
类模板:
template <class R, class X, class A>
struct const_mem_fun1_ref_t : public binary_function<X*, A, R> {
const_mem_fun1_ref_t(R (X::*f)(A)) const;
R operator()(X& x, A a) const;
};
定义头文件:<functional>
该类是binary_function
的一个派生类(C++17
之前),该类是一个成员函数适配器,如果X
是一个类,具有无任何参数的成员函数R X::f(A)
,那么mem_fun1_ref_t<R, X, A>
便成为一个成员函数适配器。
同mem_fun1_ref_t
一样,不同点在于该类只接受以const
修饰的类成员函数。
例子:
struct Calcu {
virtual double calculate(double) const = 0;
};
struct Square : public Calcu {
double calculate(double x) const {
return x * x;
}
};
struct Plus : public Calcu {
double calculate(double x) const {
return x + x;
}
};
int main() {
vector<Square> operation;
operation.push_back(Square());
operation.push_back(Square());
operation.push_back(Square());
vector<double> value = {2, 3, 4};
transform(operation.begin(), operation.end(), value.begin(), ostream_iterator<double>(cout, " "),
const_mem_fun1_ref_t<double, Calcu, double>(&Calcu::calculate));
return 0;
}
输出:
4 9 16
mem_fun_ref
用法:mem_fun_ref(R (X::*f))
定义头文件:<functional>
函数原型:
template<class Res, class X>
std::mem_fun_ref_t<Res, X> mem_fun_ref( Res (X::*f)() );
template<class R, class X>
std::const_mem_fun_ref_t<Res, X> mem_fun_ref( Res (X::*f)() const );
template<class R, class X, class Arg>
std::mem_fun1_ref_t<Res, X, Arg> mem_fun_ref( Res (X::*f)(Arg) );
template<class R, class X, class Arg>
std::const_mem_fun1_ref_t<Res, X, Arg> mem_fun_ref( Res (X::*f)(Arg) const );
该函数是以上四种成员函数适配器的一个辅助函数,该函数可以利用参数推导出该类型并返回其类型。
例子:
struct Calcu {
virtual double calculate(double) = 0;
};
struct Square : public Calcu {
double calculate(double x) {
return x * x;
}
};
struct Plus : public Calcu {
double calculate(double x) {
return x + x;
}
};
struct B {
virtual void print() const = 0;
};
struct C1 : public B {
void print() const {
cout << "C1" << endl;
}
};
struct C2 : public B {
void print() const {
cout << "C2" << endl;
}
};
int main() {
vector<Square> operation;
operation.push_back(Square());
operation.push_back(Square());
operation.push_back(Square());
vector<double> value = {2, 3, 4};
vector<C2> vec;
vec.push_back(C2());
vec.push_back(C2());
vec.push_back(C2());
transform(operation.begin(), operation.end(), value.begin(),
ostream_iterator<double>(cout, " "), mem_fun_ref(&Calcu::calculate));
cout << endl;
for_each(vec.begin(), vec.end(), mem_fun_ref(&B::print));
return 0;
}
输出:
4 9 16
C2
C2
C2
绑定器
binder1st
类定义:binder1st<BinaryFun>
类模板:
template <class Func>
class binder1st : public unary_function<typename Func::second_argument_type,
typename Func::result_type> {
binder1st(const Func& fn, const typename Func::first_argument_type& value);
typename Func::result_type
operator()(typename Func::second_argument_type& x) const;
};
定义头文件:<functional>
该类是一个函数绑定器,可以将BinaryFunction
转换成UnaryFunction
,如果说f
是一个binder1st
的对象,则f(x)
返回的是F(c, x)
,其中F
是一个BinaryFunction
,这里c
是一个常数,F
和C
都会被当作参数传给binder1st
的构造函数。
直观看,我们可以将哟个双参函数的第一参数绑定为某个常数,从而形成一个单参函数。
值得注意的是该类在C++11
已经被弃用,以使用更便捷的bind
函数,后续会介绍。
例子:
int main() {
vector<int> vec = {1, -4, 6, 4, 0, -6};
// C++11 之前
binder1st<less<int>> f1(less<int>(), 0);
// C++11 之后
auto f2 = bind(less<int>(), 0, placeholders::_1);
// 判断vec内元素x与0对比,0<x
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f1);
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f2);
return 0;
}
输出:
true false true true false false
true false true true false false
bind1st
用法:bind1st(f, x)
定义头文件:<functional>
函数原型:
template<class F, class T>
binder1st<F> bind1st(const F& f, const T& x);
该函数是binder1st
的一个辅助函数,该函数能通过参数类型推导出相应的binder1st
类,而不需要自己传入模板参数。
值得注意的是该类在C++11
已经被弃用,以使用更便捷的bind
函数,后续会介绍。
例子:
int main() {
vector<int> vec = {1, -4, 6, 4, 0, -6};
// C++11 之前
auto f1 = bind1st(less<int>(), 0);
// C++11 之后
auto f2 = bind(less<int>(), 0, placeholders::_1);
// 判断vec内元素x与0对比,0<x
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f1);
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f2);
return 0;
}
输出:
true false true true false false
true false true true false false
binder2nd
类定义:binder2nd<BinaryFun>
类模板:
template <class Func>
class binder2nd : public unary_function<typename Func::first_argument_type,
typename Func::result_type> {
binder2nd(const Func& fn, const typename Func::second_argument_type& value);
typename Func::result_type
operator()(typename Func::first_argument_type& x) const;
};
定义头文件:<functional>
该类是一个函数绑定器,可以将BinaryFunction
转换成UnaryFunction
,与binder1st
一样,区别在于该类可将双参函数的第二个参数绑定为一个参数。
值得注意的是该类在C++11
已经被弃用,以使用更便捷的bind
函数,后续会介绍。
例子:
int main() {
vector<int> vec = {1, -4, 6, 4, 0, -6};
// C++11 之前
binder2nd<less<int>> f1(less<int>(), 0);
// C++11 之后
auto f2 = bind(less<int>(), placeholders::_1, 0);
// 判断vec内元素x与0对比,x<0
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f1);
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f2);
return 0;
}
输出:
false true false false false true
false true false false false true
bind2nd
用法:bind2nd(f, x)
定义头文件:<functional>
函数原型:
template<class F, class T>
binder2nd<F> bind2nd(const F& f, const T& x);
该函数是binder2nd
的一个辅助函数,该函数能通过参数类型推导出相应的binder2nd
类,而不需要自己传入模板参数。
值得注意的是该类在C++11
已经被弃用,以使用更便捷的bind
函数,后续会介绍。
例子:
int main() {
vector<int> vec = {1, -4, 6, 4, 0, -6};
// C++11 之前
auto f1 = bind2nd(less<int>(), 0);
// C++11 之后
auto f2 = bind(less<int>(), placeholders::_1, 0);
// 判断vec内元素x与0对比,x<0
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f1);
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), f2);
return 0;
}
输出:
false true false false false true
false true false false false true
bind
用法:bind(f, x ... )
定义头文件:<functional>
函数原型:
template<class F, class... Args>
/*unspecified*/ bind(F&& f, Args&&... args);
template<class R, class F, class... Args>
/*unspecified*/ bind(F&& f, Args&&... args);
由于该函数的返回值过于复杂,后续会更新文章深入研究该返回类型,在此不进行研究。
由于bind1st
或bind2nd
只能将双参函数绑定为单参函数,因此C++11
引入该函数来进行函数参数的绑定,该函数能绑定多个参数。该函数的详细参数运用请参考官方文档。
该函数能将参数进行重排序和绑定,第一参数是函数的引用,第二参数开始则是被绑定函数的参数,若想该参数绑定为一个常数,则直接填入,若想保持该参数的“参数”效果,可使用placeholders::_1
,placeholders::_2
等占位对象,为什么用数字表示占位呢?是因为被绑定之后函数的传入参数顺序便是参照该数字顺序来进行传参。
例子:
void fun(int n1, int n2, int n3, int n4) {
cout << n1 << " " << n2 << " " << n3 << " " << n4 << endl;
}
int main() {
using namespace std::placeholders;
auto f1 = bind(fun, 1, 2, 3, 4);
f1();
auto f2 = bind(fun, 3, 4, _1, _2);
f2(5, 6);
auto f3 = bind(fun, 3, _2, _1, 4);
f3(5, 6);
return 0;
}
输出:
1 2 3 4
3 4 5 6
3 6 5 4
其他的适配器
pointer_to_unary_function
类定义:pointer_to_unary_function<Arg, Result>
类模板:
template<class Arg, class Result>
class pointer_to_unary_function : public std::unary_function<Arg, Result> {
pointer_to_unary_function(Result(*pfunc)(Arg));
Result operator()(Arg left) const;
};
定义头文件:<functional>
该类是一个函数绑定器,可以将一个函数指针看作一个UnaryFunction
来使用,如果类型为Result (*)(Arg)
的一个函数指针,它其实已经可以传入任何以单参函数为参数的STL
算法中,但它不能与去他的绑定器与适配器使用,因此可以使用该类来包装成一个真正的unary_function
的派生类。
值得注意的是该类在C++11
已经被弃用。
例子:
bool fun(int n) {
return n % 2 == 0;
}
struct fun2 : public unary_function<int, bool> {
bool operator()(int n) const {
return n % 2 == 0;
}
};
int main() {
vector<int> vec = {0, 1, 2, 3, 4};
// 单纯使用普通函数
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), fun);
// 普通函数搭配其他适配器需要包装成unary_function
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), not1(pointer_to_unary_function<int, bool>(fun)));
// 使用unary_function
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), fun2());
// 不需要包装也可使用适配器
cout << endl << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), not1(fun2()));
return 0;
}
输出:
true false true false true
false true false true false
true false true false true
false true false true false
pointer_to_binary_function
类定义:pointer_to_unary_function<Arg, Result>
类模板:
template<class Arg1, class Arg2, class Result>
class pointer_to_binary_function : public std::binary_function<Arg1, Arg2, Result> {
pointer_to_binary_function(Result(*pfunc)(Arg1, Arg2));
Result operator()(Arg1 left, Arg2 right) const;
};
定义头文件:<functional>
该类是一个函数绑定器,可以将一个函数指针看作一个BinaryFunction
来使用,如果类型为Result (*)(Arg1, Arg2)
的一个函数指针,它其实已经可以传入任何以单参函数为参数的STL
算法中,但它不能与去他的绑定器与适配器使用,因此可以使用该类来包装成一个真正的binary_function
的派生类。
值得注意的是该类在C++11
已经被弃用。
例子:
bool fun(int n, int m) {
return n * 3 + 1 == m;
}
struct fun2 : public binary_function<int, int, bool> {
bool operator()(int n, int m) const {
return n * 3 + 1 == m;
}
};
int main() {
vector<int> vec1 = {0, 1, 2, 3, 4};
vector<int> vec2 = {5, 6, 7, 8, 9};
// 单纯使用普通函数
cout << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), fun);
// 普通函数搭配其他适配器需要包装成binary_function
cout << endl << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), not2(pointer_to_binary_function<int, int, bool>(fun)));
// 使用binary_function
cout << endl << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), fun2());
// 不需要包装也可使用适配器
cout << endl << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), not2(fun2()));
return 0;
}
输出:
false false true false false
true true false true true
false false true false false
true true false true true
prt_fun
用法:prt_fun(f)
定义头文件:<functional>
函数原型:
template<class Arg, class Result>
pointer_to_unary_function<Arg,Result> ptr_fun(Result (*f)(Arg));
template<class Arg1, class Arg2, class Result>
pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*f)(Arg1, Arg2));
该函数是pointer_to_unary_function
和pointer_to_binary_function
的辅助函数,可以利用参数推导出返回值,可以不必写出模板类型。
该函数在C++11
中被弃用,因为有更加通用的function
和ref
函数,后面的文章会更新关于该方面的内容。
例子:
bool fun1(int n) {
return n % 2 == 0;
}
bool fun2(int n, int m) {
return n * 3 + 1 == m;
}
int main() {
vector<int> vec1 = {0, 1, 2, 3, 4};
vector<int> vec2 = {5, 6, 7, 8, 9};
cout << boolalpha;
transform(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "), not1(ptr_fun(fun1)));
cout << endl << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), not2(ptr_fun(fun2)));
return 0;
}
输出:
false true false true false
true true false true true
unary_negate
类定义:unary_negate<Predicate>
类模板:
template <class Predicate>
class unary_negate : public unaryFunction<typename Predicate::argument_type, bool> {
unary_negate(const Predicate& Func);
bool operator()(const typename Predicate::argument_type& left) const;
};
定义头文件:<functional>
该类是一个谓词适配器,能表示某个逻辑的负值,如果说f
是该类的对象,该类参数以函数pred()
作为底部逻辑,那么f(x)
会返回!pred(x)
的值。
严格来说,该类有点多余,因为它可以用logical_not
和unary_compose
构造出来。
值得注意的是该类在C++11
已经被弃用。
例子:
int main() {
vector<int> vec = {1, 4, 7, 0, 5, 9};
// !equal_to(0, x)
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "),
unary_negate<binder1st<equal_to<int>>>(bind1st(equal_to<int>(), 0)));
return 0;
}
输出:
true true true false true true
binary_negate
类定义:binary_negate<BinaryPredicate>
类模板:
template <class BinaryPredicate>
class binary_negate : public binaryFunction
<typename BinaryPredicate::first_argument_type,
typename BinaryPredicate::second_argument_type, bool> {
binary_negate(const BinaryPredicate& Func);
bool operator()(const typename BinaryPredicate::first_argument_type& left,
const typename BinaryPredicate::second_argument_type& right) const;
};
定义头文件:<functional>
该类是一个谓词适配器,能表示某个逻辑的负值,如果说f
是该类的对象,该类参数以函数pred(x, y)
作为底部逻辑,那么f(x, y)
会返回!pred(x, y)
的值。
值得注意的是该类在C++11
已经被弃用。
例子:
int main() {
vector<int> vec1 = {1, 4, 7, 0, 5, 9};
vector<int> vec2 = {1, 5, 8, 0, 3, 9};
// !equal_to(x, y)
cout << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "),
binary_negate<equal_to<int>>(equal_to<int>()));
return 0;
}
输出:
false true true false true false
not1
用法:not1(f)
定义头文件:<functional>
函数原型:
template<class Predicate>
unary_negate<Predicate> not1(const Predicate& pred);
该函数是一个unary_negate
的辅助函数,可以根据参数的类型推导出unary_negate
类,方便我们,不用学出类的模板参数。
例子:
int main() {
vector<int> vec = {1, 4, 7, 0, 5, 9};
// !equal_to(0, x)
cout << boolalpha;
transform(vec.begin(), vec.end(), ostream_iterator<bool>(cout, " "), not1(bind1st(equal_to<int>(), 0)));
return 0;
}
输出:
true true true false true true
not2
用法:not2(f)
定义头文件:<functional>
函数原型:
template<class BinaryPredicate>
binary_negate<BinaryPredicate> not2(const BinaryPredicate& pred);
该函数是一个binary_negate
的辅助函数,可以根据参数的类型推导出binary_negate
类,方便我们,不用学出类的模板参数。
例子:
int main() {
vector<int> vec1 = {1, 4, 7, 0, 5, 9};
vector<int> vec2 = {1, 5, 8, 0, 3, 9};
// !equal_to(x, y)
cout << boolalpha;
transform(vec1.begin(), vec1.end(), vec2.begin(), ostream_iterator<bool>(cout, " "), not2(equal_to<int>()));
return 0;
}
输出:
false true true false true false