std::bind
返回一个function object,可以绑定:
- functions;
- function objects;
- member functions,
_1
必须是某个object地址; - data members,
_1
必须是某个object.
写
std::bind()
时参数或std::placeholders
出现的顺序、原函数参数的顺序、新函数参数的顺序,是怎么对应的?
- 写
std::bind()
时参数或std::placeholders
出现的顺序与原函数参数是一一对应的;- 新函数参数与
std::bind()
的std::placeholders
是一一对应的,即新函数的第一个参数对应于_1
,新函数的第二个参数对应于_2
,依此类推。
1. bind的一般使用方式
#include <functional>
#include <string>
#include <iostream>
void check(const std::string& name, int age) {
std::cout << name << " " << age << std::endl;
}
int main()
{
/* placeholders表示的是newcallable的参数 */
// newcallable1的第一个参数放到_1处,第二个参数放到_2处
auto newcallable1 = std::bind(check, std::placeholders::_1, std::placeholders::_2);
newcallable1("yujia", 1);
// newcallable2的第一个参数放到_1处,第二个参数放到_2处,相当于newcallable1的参数互换
auto newcallable2 = std::bind(check, std::placeholders::_2, std::placeholders::_1);
newcallable2(1, "yujia");
auto newcallable3 = std::bind(check, std::placeholders::_1, 1);
newcallable3("yujia");
// newcallable4的第二个参数放到_2处
// 因此即使只有一个placeholder当调用newcallable4的时候还是要提供两个参数
// 但是调用newcallable4时提供的参数是没用的
auto newcallable4 = std::bind(check, std::placeholders::_2, 25);
newcallable4(123,"yujia"); // 输出:yujia 25, 而不是:yujia 123
return 0;
}
输出:
1.1 bind的函数参数有引用
#include <functional>
#include <fstream>
#include <string>
#include <iostream>
std::ostream& Print(std::ostream & of, std::string& str, int i) {
return of << str << " " << i << std::endl;
}
using namespace std::placeholders;
int main()
{
std::ofstream out_file("ref.txt");
std::string str = std::string("content sample");
// 如果out_file不用placeholder方式则需要使用std::ref,因为其不可复制
#if 0
auto newCallable = std::bind(Print, std::ref(out_file), _1, _2);
newCallable(str, 65);
#endif
#if 1 // 使用placeholder则没有必要使用std::ref(当然也可以使用)
auto newCallable = std::bind(Print, _3, _1, _2);
newCallable(str, 45, out_file);
#endif
return 0;
}
2. std::bind
和其绑定的函数之间有个中间层
#include <iostream>
#include <functional>
namespace test_ref
{
void func(int& a, int& b, const int& c)
{
++a;
++b;
}
auto main() -> int
{
std::cout << "testing ref......\n" << std::endl;
{
int a = 1, b = 1, c = 1;
func(a,b,c);
std::cout << a << ", " << b << ", " << c << std::endl; // 2 2 1
}
{
int a = 1, b = 1, c = 1;
// 如果不加std::ref,则给bind传递的是copy of a,然后再将a的拷贝传给func
auto bfunc = std::bind(func, a, std::ref(b), std::cref(c));
bfunc();
std::cout << a << ", " << b << ", " << c << std::endl; // 1 2 1
}
std::cout << "------------------------------" << std::endl;
return 0;
}
}
3. std::bind<int/double/class/struct>
?
#pragma once
#include <iostream>
#include <functional>
#include <string>
namespace test_bind
{
struct Foo{
int data_;
double divide(double n1, double n2){
if(n2){return n1 / n2;}
else return 0;
}
};
using namespace std::placeholders;
auto main()-> void {
std::cout << "test_bind......." << std::endl;
// 使用bind用函数代替数据成员,使用placeholder
auto bind2mem1 = std::bind(&Foo::data_, _1);
Foo f{20};
std::cout << bind2mem1(f) << std::endl;
// 使用bind用函数代替数据成员,直接绑定类对象
auto bind2mem2 = std::bind(&Foo::data_, &f);
std::cout << bind2mem2() << std::endl;
std::cout << std::string(20,'-') << std::endl;
// 使用bind绑定到函数成员
auto bind2memfunc1 = std::bind(&Foo::divide, _2, _1, _3);
std::cout << bind2memfunc1(15, &f, 2) << std::endl;
auto bind2memfunc2 = std::bind(&Foo::divide, &f, _1, _2);
std::cout << bind2memfunc2(17,2) << std::endl;
auto bind2memfunc = std::bind<int>(&Foo::divide, &f, 19, 2);
std::cout << bind2memfunc() << std::endl;
std::cout << "test_bind pass\n----------------------------" << std::endl;
}
}
输出:
test_bind.......
20
20
--------------------
7.5
8.5
9
test_bind pass
----------------------------