STL常见算法与适配器运用(下)

这篇文章,虽然叫做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 S1S2 也就是说,当且仅当[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 S1S2,该集合内含两个集合的每一个不等价元素,返回值为输出迭代器的尾端。如果在两个集合出现等价元素,那么在输出集合中该元素肯定来自第一个集合。

同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用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 S1S2,该集合内含两个集合的每一个等价元素,返回值为输出迭代器的尾端。这些元素都来自第一个集合。

同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用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);

该算法能创建出两个集合的两集合之差,即s1s2的补集, S 1 − S 2 S_1 - S_2 S1S2,返回值为输出迭代器的尾端。

同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用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) (S1S2)(S2S1),返回值为输出迭代器的尾端。

同样的,该函数也有两个版本区别在于等价元素的判断的不同,第一个版本使用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);

该函数可以返回迭代器firstlast的路程,该迭代器必须可以从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+运算,返回值则为xy的元素之和。

例子

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-运算,返回值则为xy的元素之差。

例子

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*运算,返回值则为xy的元素之积。

例子

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/运算,返回值则为xy的元素之商。

例子

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%运算,返回值则为xy的元素之模。

例子

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是一个常数,FC都会被当作参数传给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);

由于该函数的返回值过于复杂,后续会更新文章深入研究该返回类型,在此不进行研究。

由于bind1stbind2nd只能将双参函数绑定为单参函数,因此C++11引入该函数来进行函数参数的绑定,该函数能绑定多个参数。该函数的详细参数运用请参考官方文档。

该函数能将参数进行重排序和绑定,第一参数是函数的引用,第二参数开始则是被绑定函数的参数,若想该参数绑定为一个常数,则直接填入,若想保持该参数的“参数”效果,可使用placeholders::_1placeholders::_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_functionpointer_to_binary_function的辅助函数,可以利用参数推导出返回值,可以不必写出模板类型。

该函数在C++11中被弃用,因为有更加通用的functionref函数,后面的文章会更新关于该方面的内容。

例子

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_notunary_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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值