前言

本篇为本人手写全套实战笔记,包含 bitset位图操作、自定义仿函数、STL内置仿函数、Lambda表达式、bind参数绑定器、STL常用算法。


一、bitset 位图容器(位运算神器)

1.1 核心概念

bitset<N>:固定N位二进制位图容器,默认全部置0,专门用于位运算、权限判断、状态标记、进制转换。

优势:极度省内存、位运算效率极高。

1.2 常用API

  • set():所有位置1

  • set(pos,val):指定位置置0/1

  • reset():所有位置0

  • flip():所有位按位取反

  • to_ulong():二进制转十进制

  • 支持位运算:& | ^ ~

  • 支持位图之间判等 ==

1.3 完整实战代码

#include<iostream>
#include<bitset>
using namespace std;

int main() {
	// 固定2位二进制,默认全0
	bitset<2> pb;    
	cout << pb << endl;

	pb.set();        // 全部置1
    cout << pb << endl;

	pb.reset();      // 全部重置为0

	pb.set(0, 1);    // 第0位置1
	cout << pb << endl;

	// 字符串转二进制位图
	bitset<8> pbs("10101010");
	// 十进制数值转二进制位图
	bitset<3> fb(6);
	cout << fb << endl;

	fb.flip();       // 所有位取反
    cout << fb << endl;

	// 位图比较
	bitset<3> fb2(5);
    cout << (fb2 == fb) << endl;

	// 权限位运算模拟
	bitset<3> r(4), w(2), x(1);
	// 判断是否拥有x权限
	if ((fb2 & x) == x) {
		cout<<"具有可执行权限"<<endl;
	}

	// 增加w权限
	fb2 |= w;
	cout << fb2 << endl;

	// 移除w权限(异或翻转)
	fb2 ^= w;
    cout << fb2 << endl;

	// 二进制字符串转十进制
	bitset<8> data("1001001");
    cout << data.to_ulong() << endl;

	// 字符转二进制(a=97)
    bitset<8> data2('a');
    cout << data2 << endl;

	return 0;
}

1.4 课后练习代码

#include<iostream>
#include<string>
using namespace std;

// 自定义仿函数类
class F {
public:
	void operator() (const string &info) const{
		cout << "info:"<<info << endl;
	}
};

int main() {
	F f;
    f("hello world"); // 像函数一样调用
	return 0;
}

二、仿函数(函数对象)

2.1 核心概念

仿函数:重载了 operator() 的类对象,可以像函数一样调用。

特点:可以保存成员变量状态、支持一元/二元运算、后期可被Lambda替代。

2.2 基础无状态仿函数

#include<iostream>
#include<string>
using namespace std;

// 自定义仿函数类
class F {
public:
	void operator() (const string &info) const{
		cout << "info:"<<info << endl;
	}
};

int main() {
	F f;
    f("hello world"); // 像函数一样调用
	return 0;
}

2.3 一元/二元 带状态仿函数

#include<iostream>
using namespace std;

class Add1 {
public:
	Add1() { v = 0; }
	Add1(int v) :v(v) {}

	// 二元仿函数
	int operator() (int a, int b) const {
		return a + b;
	}
	// 一元仿函数
	int operator() (int a) const {
		return a + v;
	}
private:
	int v;
};

int main() {
	Add1 add1(100);
    cout << add1(10, 20) << endl;
	cout << add1(10) << endl;

	Add1 add(0);
	cout<<add(10)<<endl;
	cout<<add(20)<<endl;
	cout<< add(30)<<endl;

	return 0;
}

2.4 谓词仿函数(返回bool)

谓词:仿函数返回值为bool类型,分为一元谓词、二元谓词,多用于STL算法判断条件。

#include<iostream>
using namespace std;

// 二元谓词:a >= b
class GreaterEqual {
public:
    bool operator() (int a, int b) const {
        return a >= b;
    }
};

// 一元谓词:取反
class Not {
public:
    bool operator() (bool b) const {
		return !b;
    }
};

int main() {
	GreaterEqual ge;
	Not _not;
    cout << boolalpha<<ge(10, 20) << endl;
    cout << boolalpha<<_not(ge(10, 20)) << endl;
	return 0;
}

2.5 STL 内置仿函数(头文件 <functional>)

STL内置大量现成仿函数,无需自己手写,可直接配合算法、bind使用。

分类:算术运算、关系运算、逻辑运算、位运算

#include<iostream>
#include<functional>
using namespace std;

int main() {
	// 算术仿函数
	multiplies<int> mul;
    cout << mul(10, 20) << endl;

	plus<int> p;
    cout << p(10, 20) << endl;

	minus<int> m;
    cout << m(10, 20) << endl;

	divides<int> d;
    cout << d(10, 20) << endl;

    modulus<int> mod;
    cout << mod(10, 20) << endl;

    negate<int> ne;
    cout << ne(10) << endl;

	// 关系仿函数
	not_equal_to<int> neq;
	cout<< neq(10,20)<<endl;

	// 自动推导类型
	less<> f2;
    cout<<f2(10,20)<<endl;

	// 逻辑仿函数
	logical_and<> f3;
    cout<<f3(f2(3,2),f2(10,20))<<endl;

    return 0;
}

三、Lambda表达式(重点,替代仿函数)

3.1 核心作用

定义匿名函数,替代繁琐的自定义仿函数,写法简洁、适合临时逻辑、配合STL算法使用。

3.2 标准语法

[捕获列表](参数列表) mutable -&gt; 返回值类型 { 函数体 }

捕获规则

  • []:不捕获任何变量

  • [=]:值捕获所有局部变量(只读)

  • [&]:引用捕获所有局部变量(可修改原变量)

  • [a,b]:值捕获指定变量

  • [&a]:引用捕获指定变量

  • mutable:允许修改值捕获的副本变量

3.3 基础Lambda使用

#include<iostream>
using namespace std;

int main() {
	// 二元加法Lambda
	auto _plus_f = [](int a, int b) ->int { return a + b; };
	cout<< _plus_f(10, 20) << endl;

	// 二元比较谓词
	auto gt_f = [](int a, int b)->bool {return a > b; };
	cout<<boolalpha<< gt_f(10, 20) << endl;

	// 一元输出
	auto show_f = [](int v) { cout << v << endl; };
    show_f(10);

	// 无参匿名函数
	auto hi = [] { cout << "hello lambda" << endl; };
    hi();

	return 0;
}

3.4 变量捕获 + mutable修改

#include<iostream>
using namespace std;

int main() {
	int a =10, b = 5;
	int* ap = &a;

	// 值捕获 + mutable 允许修改副本
	auto f = [a, b]() mutable{
		cout<<"lambda a++ = " << ++a << endl;
		cout << "lambda a+b = " << a+b << endl;
	};

	cout<< "main a = " << a << endl;
    f();
   	cout<< "main a = " << a << endl;

	// 值捕获指针:可修改指向内容
	auto f1 = [=](int v) {
		*ap += v;
	};

	f1(10);
    cout << "main a = " << a << endl;

	return 0;
}

四、bind 参数绑定器

4.1 核心作用

将多元仿函数降维(二元转一元),固定部分参数,剩余参数用占位符接收。

占位符:placeholders::_1、_2... 代表调用时传入的第N个参数。

4.2 实战代码

#include<iostream>
#include<functional>
using namespace std;

int main() {
	plus<> _add;
	cout << _add(10, 20) << endl;

	// 固定第一个参数10,二元降一元
	auto _add1 = bind(_add, 10, placeholders::_1);
	cout << _add1(20) << endl;

	// 固定第二个参数20
	auto _add2 = bind(_add, placeholders::_1, 20);
   	cout << _add2(30) << endl;

	return 0;
}

五、STL 常用算法(核心重点)

头文件:<algorithm> <functional> <iterator>

5.1 遍历算法 for_each

#include<iostream>
#include<vector>
#include<deque>
#include<list>
#include<map>
#include<algorithm>
using namespace std;

// 重载输出,适配所有容器
ostream& operator<<(ostream& out, deque<int>& v) {
	for_each(v.begin(), v.end(), [](int item) {
		cout<<item<<" ";
	});
	cout << endl;
	return out;
}
ostream& operator<<(ostream& out, list<int>& v) {
	for_each(v.begin(), v.end(), [](int item) {
		cout << item << " ";
		});
	cout << endl;
	return out;
}
ostream& operator<<(ostream& out, vector<int>& v) {
	for_each(v.begin(), v.end(), [](int item) {
		cout << item << " ";
		});
	cout << endl;
	return out;
}
ostream& operator<<(ostream& out, map<int, int>& v) {
	for_each(v.begin(), v.end(), [](pair<int, int> item) {
		cout << item.first << " " << item.second << " ";
		});
	cout << endl;
	return out;
}

int main() {
	vector<int > v{ 9,1,2,4,8,2,3,3,9,5,4,1 };
	cout << v;

	deque<int> d{ v.begin(),v.end()};
	cout<< d;

	list<int> l{ v.begin(),v.end() };
	cout << l;

   	map<int, int> m{ {1,2},{3,4},{5,6} };
	cout << m;

	return 0;
}

5.2 查找算法 find / find_if

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<ctime>
using namespace std;

// 生成随机数
void genRandom(vector<int>& v, int len, int _min, int _max) {
	srand(time(NULL));
	v.clear();
	for (int i = 0; i < len; i++) {
      v.push_back(rand() % (_max - _min+1) + _min);
	}
}

int main() {
	vector<int> v;
	genRandom(v, 10, 1, 100);
	for_each(v.begin(), v.end(), [](int item) {cout << item<<" "; });
	cout << endl;

	// 精准查找
	vector<int>::iterator it=find(v.begin(), v.end(), 90);
	if (it != v.end()) {
       cout << "精准查找:OK" << endl;
	}
	else {
		cout<< "精准查找:NO" << endl;
	}

	// 条件查找:找第一个小于50的数
	auto it2 = find_if(v.begin(), v.end(), bind(less<>(),placeholders::_1,50));
	if (it2 != v.end()) {
		cout<< "条件查找:OK" << endl;
	}
	else {
        cout << "条件查找:NO" << endl;
	}

	return 0;
}

5.3 子序列搜索 search

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;

int main() {
	vector<int> v1{ 3,8,7,2,1,3,4,5,6 };
	vector<int> v2{ 1,2,3,5 };

	auto it = search(v1.begin(), v1.end(), v2.begin(), v2.end());
	if (it != v1.end())
	{
		cout<< "容器子序列匹配:OK" << endl;
	}
	else {
       	cout << "容器子序列匹配:NO" << endl;
	}

	// 字符串子串查找
	string s1 = "hi,disen";
	string s2 = "disen";
	auto it2 =  search(s1.begin(), s1.end(), s2.begin(), s2.end());
	if (it2 != s1.end())
	{
		cout << "字符串子串匹配:OK" << endl;
	}
	else {
		cout << "字符串子串匹配:NO" << endl;
	}

	return 0;
}

5.4 count_if 条件统计

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<ctime>
using namespace std;

void genRandom(vector<int>& v, int len, int _min, int _max) {
	srand(time(NULL));
	v.clear();
	for (int i = 0; i < len; i++) {
		v.push_back(rand() % (_max - _min + 1) + _min);
	}
}

int main() {
	vector<int> v;
	genRandom(v, 10, 1, 100);

	// 统计小于50的元素个数
	int cnt = count_if(v.begin(),v.end(),bind(less<>(),placeholders::_1,50));
	cout << "小于50的元素个数:" << cnt << endl;

	return 0;
}

5.5 copy_if / transform 复制与变换

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<iterator>
#include<ctime>
using namespace std;

void genRandom(vector<int>& v, int len, int _min, int _max) {
	srand(time(NULL));
	v.clear();
	for (int i = 0; i < len; i++) {
		v.push_back(rand() % (_max - _min + 1) + _min);
	}
}

int main() {
	vector<int> v;
	genRandom(v, 10, 1, 100);
	vector<int> v2;

	// copy_if:复制大于等于70的元素
	copy_if(v.begin(),v.end(),back_inserter(v2), bind(greater_equal<int>(), placeholders::_1, 70));
	for_each(v2.begin(), v2.end(), [](int item) {cout << item << " "; });
    cout << endl;

	// transform:元素转换映射
	vector<bool>  flags;
	transform(v.begin(), v.end(), back_inserter(flags), [](int v)->bool{return v > 90; });

	return 0;
}

5.6 综合练习:字符串处理

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<functional>
#include<iterator>
using namespace std;

int main() {
	vector<string> v{ "hello","world","disen","cpp","java","c++","c#","python","php" };
	vector<string> v2;
	vector<int> v3;
	vector<pair<string,int>> v4;

	// 筛选长度大于3的字符串
	copy_if(v.begin(), v.end(), back_inserter(v2), bind([](string a, int size) {return a.size() > size; }, placeholders::_1, 3));
	for_each(v2.begin(),v2.end(), [](string item) {cout << item << " "; });
	cout << endl;

	// 转换为字符串长度
	transform(v.begin(),v.end(),back_inserter(v3), [](string item)->int {return item.size(); });
    for_each(v3.begin(), v3.end(), [](int item) {cout << item << " "; });
	cout << endl;

	// 转换为pair数组
	transform(v.begin(), v.end(), back_inserter(v4), [](string item)->pair<string, int> {
		pair<string, int> p(item, item.size());
		return  p; });
    for_each(v4.begin(), v4.end(), [](pair<string, int> item) {cout << item.first << " " << item.second << " "; });
	cout << endl;

	return 0;
}

六、核心总结

  • bitset:固定长度位图,高效位运算、权限判断、进制转换

  • 仿函数:重载()的类对象,可存状态,分一元/二元/谓词,可被Lambda替代

  • Lambda:匿名函数,捕获外部变量,mutable修改值捕获副本,简洁适配STL算法

  • bind绑定器:多元函数降维,固定参数+占位符传参

  • STL算法:for_each遍历、find查找、search子序列、count_if统计、copy_if复制、transform元素转换

  • 所有算法均配合 仿函数/bind/lambda 实现自定义条件,是STL核心精髓

更多推荐