介绍c++

C++ 这门编程语言的历史可以追溯至 1979 年,当时的 Bjarne Stroustrup(C++ 之父,后续简称 Stroustrup)还在使用 Simula 语言进行开发工作。

1998年,C++ 标准委员会发布了第一版 C++ 标准,并将其命名为 C++98 标准。据不知名人士透露,《带注释的C++参考手册》这本书对 C++98 标准的制定产生了很大的影响。

2011年,新的 C++11 标准诞生,用于取代 C++98 标准。

2014年,C++14 标准发布,该标准库对 C++11 标准库做了更优的修改和更新;

2017年底,C++17 标准正式颁布;

std::bind原型

查看bind函数,发现它实际为两个模板函数。

1
2
3
4
5
6
7
8
9
10
11
// FUNCTION TEMPLATE bind (implicit return type)
template <class _Fx, class... _Types>
_NODISCARD _CONSTEXPR20 _Binder<_Unforced, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args) {
return _Binder<_Unforced, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
}

// FUNCTION TEMPLATE bind (explicit return type)
template <class _Ret, class _Fx, class... _Types>
_NODISCARD _CONSTEXPR20 _Binder<_Ret, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args) {
return _Binder<_Ret, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
}

它实际上是使用一个可调用对象,通过绑定一些参数生成一个新的可调用对象。这里注意一下细节,说的是可调用对象而不是可调用接口函数。

std::bind绑定的可调用对象有:

  • 普通函数,静态函数,模板函数;
  • 类成员函数,类成员静态函数,类成员模板函数,类成员变量,类内部绑定;
  • 仿函数,Lambda表达式。

std::bind使用

绑定1

绑定普通函数,静态函数,模板函数。举例说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//普通函数
void fun1(int i, int j) {
cout << (i > j ? i : j) << endl;
}

//静态函数
static void fun2(int i, int j) {
cout << (i > j ? i : j) << endl;
}

//模板函数
template <typename T1 = int, typename T2 = int>
void fun3(T1 i, T2 j) {
cout << (i > j ? i : j) << endl;
}

int main() {
auto fun1Test = bind(fun1, 1, 2);
auto fun2Test = bind(fun2, 1, 2);
auto fun3Test = bind(fun3<>, 1, 2);

fun1Test();
fun2Test();
fun3Test();

return 0;
}

结果都为2。

绑定2

类成员函数、类成员静态函数、类成员模板函数、类成员变量、类内部绑定。

这部分比较重要的就是要明白普通函数和类成员函数有什么区别,我们都知道的是在函数指针上面,类成员函数指针不仅要指定目标函数的形参列表和返回类型,还必须指出成员函数所属的类。

当然类的静态成员不属于任何对象,因此无须特殊的指向静态成员的指针,指向静态成员的指针与普通指针没有什么区别。

所以我们在bind类成员函数时,需要显示的传入类对象、或者类对象的引用、或者类对象的指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Test
{
public:
void fun1(int i, int j) { cout << (i > j ? i : j) << endl; } //类成员普通函数

static void fun2(int i, int j) { cout << (i > j ? i : j) << endl; } //类静态函数

template <typename T1 = int, typename T2 = int>
void fun3(T1 i, T2 j) { cout << (i > j ? i : j) << endl; } //类模板函数

void fun4() { auto fun1Test = bind(&Test::fun1, this, 1, 2); fun1Test(); }; //类内部使用

public:
int m_X = 10;
};

int main()
{
Test test;
Test* pTest = &test;
auto fun1Test = bind(&Test::fun1, test, 1, 2); //传入类对象
auto fun2Test = bind(Test::fun2, 1, 2); //因为静态函数,所以无需传入类
auto fun3Test = bind(&Test::fun3<>, &test, 1, 2); //传入类引用
auto memberVar = std::bind(&Test::m_X, pTest); //传入类对象指针

fun1Test();
fun2Test();
fun3Test();
test.fun4(); //类内部使用,直接使用this
cout << memberVar() << endl;

return 0;
}

绑定3

绑定仿函数、Lambda表达式。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Compare {
public:
void operator()(int i, int j) { cout << (i > j ? i : j) << endl; }
};

int main()
{
auto fun1 = bind(Compare(), 1, 2); //仿函数自动实例化
auto fun2 = bind([](int i, int j) {cout << (i > j ? i : j) << endl; }, 1, 2); //匿名函数
fun1();
fun2();
return 0;
}

占位符

占位符是用于表明要绑定的参数在生成新的可执行对象的位置。有的时候我们不需要立马进行绑定,或者不需要全部进行绑定,甚至是需要改变参数传入的顺序时候使用。

1
2
3
4
5
6
7
8
9
10
11
12
void fun(int i, int j = 2) { cout << (i > j ? i : j) << endl; }

int main()
{
auto fun1 = bind(fun, 1, std::placeholders::_1);
auto fun2 = bind(fun, std::placeholders::_1, 2); //第二个参数必须输入,这个时候不识别默认参数
auto fun3 = bind(fun, std::placeholders::_2, std::placeholders::_1);
fun1(2);
fun2(1);
fun3(1, 2); //此时1作为第二个参数输入,2作为第一个参数输入
return 0;
}

转自:https://blog.csdn.net/qq_42956179/article/details/115518826