C++常用标准库函数
文章目录
<functional>
函数(组件):std::bind() 、std::ref()、std::funcion()
命名空间:placeholders
类模板:greater 和 less
bind()
target = bind(func, argslist)
- func为可调用对象,bind()返回一个可调用对象,此处target为可调用对象
- 浅显的可将target视作一个函数,在调用target时,需要满足target(arglist)规则。
- 换句话说,我们可看做,bind(func,argslist) 相当于给func() 的部分参数设置了临时默认值,使用target来调用func()函数时,只需要补足余下缺少的参数。
- 通过以下举例来完善理解,某些函数被调用时只允许携带一个传参,这时我们就可以使用bind()帮忙。
void func(int x, int y){
cout<<x << " "<< y<< endl;
}
auto target = bind(func, _1, b);
target(a); // 等价于func(a, b);
- 以上例子中的
_1
格式详见,是一种占位符,代表我们需要向target传递某个参数,而这个参数在func中时第_1
个参数。 - 我们也可以使用bind帮忙,让参数的传递顺序有变
// 假设f有五个形参,如此书写,g中的第一个参数将传递到f的第五个参数位,而g中的第二个参数将传递到f的第三个参数位
auto g = bind(f, a, b, _2, c ,_1);
g(X, Y); // 等价于f(a, b, Y, c, X);
- bind()拷贝其参数,面对一个不能拷贝的参数时,我们需要用到引用,可用ref()函数帮忙
命令空间:placeholders
该命名空间存放有_n
格式的占位符,而placeholders
存放在std
占位空间,故如果我们没有用using命令时,需要这样书写:std::placeholers::_1
std::ref()
std::ref()用于将对象包装成引用包装器(reference wrapper)。这个函数通常用于将对象作为引用传递给函数或者函数对象,从而允许对该对象进行修改。
需要注意的是,引用包装器并不是引用本身,但可以模拟引用的行为,因此可以安全地传递给接受引用参数的函数。
组件:std::function
std::function是标准库组件,一个强大而灵活的工具。
作用:将可调用对象封装为一个函数对象,提供一种统一的方式来处理各种类型的可调用函数
基本语法
std::function<T(args)> funcname;
示例
#include<iostream>
#include<functional>
class MyClass{
public:
// 重载()运算法,使MyClass可作为函数调用
void operator()() const{
std::cout << "MyClass is Callable" << std::endl;
}
};
void greet(){
std::cout << "Hello" << std::endl;
}
int main(){
// (1)封装函数指针
std::function<void()> func1 = greet;
func1(); // 将调用封装的函数指针,打印"Hello"
// (2) 封装lambda表达式
std::function<void()> func2 = [](){
std::cout <<" Lambda! " <<std::endl;
};
func2(); // 调用封装的lambda表达式,打印"Lambda"
//封装可调用对象
std::function<void()> func3 = MyClass();
func3(); // 打印"MyClass is Callable"
return 0;
}
组合使用示例:
#include <iostream>
#include <functional>
void printMessage(const std::string& message, int value) {
std::cout << message << ": " << value << std::endl;
}
int main() {
std::function<void(int)> func = std::bind(printMessage, "Hello", std::placeholders::_1);
func(42); // 输出 Hello: 42
return 0;
}
类模板:greater和less
greater
和less
都是标准库中的函数对象类模板。
作用:通常用于算法的比较器,用于指定比较顺序。
说明:其重载了()
运算法,接受两个参数,比较其大小,返回一个bool值。
- greater指定: first_para > second_para
- less指定: first_para < second_para
模板代码如下
template <class T> struct greater {
bool operator() (const T& x, const T& y) const {return x>y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
template <class T> struct less {
bool operator() (const T& x, const T& y) const {return x<y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
用途:可以被用作容器的排序谓词,或者传递给一些需要比较器参数的算法。
#include<iostream>
#include<vector>
#include<iterator>
#include<functional>
#include<algorithm>
using namespace std;
int main()
{
int A[] = {1,4,3,7,10};
const int N = sizeof(A) / sizeof(int);
vector<int> vec(A, A+N);
ostream_iterator<int> output(cout, " ");
cout<<"Vector vec contains:";
copy(vec.begin(), vec.end(), output);
cout<<"\nAfter greater<int>():";
sort(vec.begin(), vec.end(), greater<int>());//内置类型从大到小
copy(vec.begin(), vec.end(), output);
cout<<"\nAfter less<int>():";
sort(vec.begin(), vec.end(), less<int>()); //内置类型小大到大
copy(vec.begin(), vec.end(), output);
return 0;
}
模板类:std::hash
作用:提供了一种标准的哈希函数的实现,可以用于各种数据类型的哈希计算
语法:
namespace std {
template< class T >
struct hash;
}
使用方法:通过模板参数类型T
进行特化,可以得到对应类型的哈希函数对象。
// 示例1 针对内置基本数据类型
std::hash<int> hash_fn; // 创建一个hash函数对象
int value = 42;
size_t hash_value = hash_fn(value); // 可得到value的hash值
// 示例2 对自定义类型进行哈希
struct MyStruct{
int a;
std::string b;
};
// 特化 std::hash 模板,定义哈希函数对象
namespace std{
template<>
struct hash<MyStruct>{
// 重载()运算符
size_t operator()(const Mystruct& s) const {
size_t hash_a = std::hash<int>{}(s.a);
size_t hash_b = std::hash<std::string>{}(s.b);
// hash_b << 1 左移一位
// ^ 异或运算,相同为0,相异为1
return hash_a ^ (hash_b << 1);
}
};
}
<utility>
参考:
[1] 《C++ Primer(第五版)》 by: Stanly B.Lippman, Josee Lajoie, Barbara E.Moo
[2] 知乎:理解C++ std::function灵活性与可调用对象的妙用
[3] CSDN: Toryci——C++ greater<int>()和less<int>()
see Lajoie, Barbara E.Moo