简介
- C++
标准库
引用包装器 std::ref
-
我们经常需要处理各种各样的对象和函数调用,其中一个常见的问题是如何高效地传递对象。如果不注意,很容易引入不必要的拷贝开销和性能损失
-
什么是std::ref
- std::ref是 C++11 标准库中的一个函数模板,用于生成一个引用包装器。引用包装器本质上是对一个对象的引用进行封装,使得在某些场景下能够更加方便的传递和使用引用。
- 例如,在标准库的算法和多线程库中,经常需要传递引用,而std::ref可以帮助我们简化这一过程。
为什么需要引用包装器
- 在C++中,函数传参时有几种常见方式,每种方式都有其使用的场景和特点
- 按值传递: 会创建参数对象的副本,可能带来额外的性能开销
- 按指针传递:需要显式的处理指针,可能导致代码复杂性增加
- 按引用传递:无需创建副本,性能较高,但是在某些场景下使用起来不够方便
- 在需要保持对象的引用关系,但是又不想显示地使用指针或者引用时,引用包装器 std::ref 就派上用场了
如何使用std::ref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <functional> // 引入std::ref
void increment(int& n) {
++n;
}
void call_increment() {
int x = 5;
std::function<void()> f = std::bind(increment, std::ref(x));
f();
std::cout << "x after increment: " << x << std::endl; // 输出:x after increment: 6
}
int main() {
call_increment();
return 0;
}
- 在这个例子中,std::bind用于绑定函数increment和参数x,而std::ref确保传递的是x的引用,而不是副本。
std::ref在多线程中的应用
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
#include <iostream>
#include <thread>
#include <vector>
#include <functional>
void add_to_counter(int& counter, int num_iterations) {
for (int i = 0; i < num_iterations; ++i) {
++counter;
}
}
int main() {
int counter = 0;
int num_threads = 10;
int num_iterations = 1000;
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back(add_to_counter, std::ref(counter), num_iterations);
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final counter value: " << counter << std::endl; // 输出:Final counter value: 10000
return 0;
}
- 在这个例子中,我们创建了10个线程,每个线程对同一个counter变量进行了1000次累加 操作。通过使用std::ref,我们确保每个线程操作的是同一个counter引用,而不是副本。
std::ref 与 std::cref
- 除了 std::ref,C++标准库还提供了 std::cref,用于生成常量引用的包装器。
- std::cref的使用方式与std::ref类似,不同之处在于它生成的是const引用,确保被引用的对象在使用过程中不会被修改。 ```cpp
#include
void print_value(const int& n) { std::cout « “Value: “ « n « std::endl; }
int main() { int x = 5; std::function<void()> f = std::bind(print_value, std::cref(x)); f(); // 输出:Value: 5 return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+ 在这个例子中,std::cref确保传递的是x的常量引用,print_value函数无法修改x的值。
### std::ref的内部实现
+ 虽然我们平时使用std::ref时只需要调用它的接口,但了解其内部实现有助于我们更深入地理解它的工作原理。std::ref的内部实现实际上非常简单,它定义了一个模板类reference_wrapper,用于封装引用。下面是一个简化的实现版本:
```cpp
template <typename T>
class reference_wrapper {
public:
explicit reference_wrapper(T& ref) : ref_(std::addressof(ref)) {}
operator T&() const { return *ref_; }
T& get() const { return *ref_; }
private:
T* ref_;
};
template <typename T>
reference_wrapper<T> ref(T& t) {
return reference_wrapper<T>(t);
}
- 可以看出,reference_wrapper通过保存一个指向引用对象的指针,实现了对引用的包装。
- std::ref函数只是创建了一个reference_wrapper对象并且返回。
std::ref 小结
- std::ref 作为C++标准库中的一个小工具,虽然看似简单,但是在实际编程中却能够解决很多复杂的问题。
- 它不仅能够简化函数参数传递,还能在多线程编程中确保引用的正确传递,从而提升代码的性能和可读性。
什么是 std::function
- std::function 是C++11引入的一个函数包装器类型。它的主要作用是,将任何可调用实体(比如函数,lambda表达式,函数指针或者函数对象)都包装成一个统一的对象,从而可以统一的保存,传递和调用这些可调用实体。
-
简单的说,std::function就是一个可以容纳各种可调用实体的容器。我们可以将它看作是一个通用的函数指针,但是它比普通的函数指针更加灵活和强大。
- std::function 提供了一种非常灵活和通用的方式来处理可调用实体,包括普通函数,lambda表达式以及函数对象。
- 它的主要优点包括
- 统一的函数调用接口,简化了代码
- 可以存储在容器中,增强了代码的可扩展性
- 可以与std::bind()结合使用,实现参数绑定等高级功能
C++ 标准库
<functional>
标准库是 C++ 中的一个头文件,提供了函数对象(Function Object)的支持,包括了一些预定义的函数对象和函数适配器。它使得函数能够像对象一样被传递、存储、返回以及调用。
这个库中的重要组件包括:
1. 函数对象(Function Objects)
函数对象是可以像函数一样被调用的对象。在 <functional>
中有一些内置的函数对象,如:
std::function
:用于封装可调用的目标,可以是函数指针、函数、成员函数、Lambda 表达式等,是一种通用的函数封装器。std::bind
:用于创建函数对象,可绑定函数或者成员函数到指定的参数上。std::placeholders
:用于占位符,在使用std::bind
绑定函数时,指定部分参数留待后续提供。
2. 函数适配器(Function Adapters)
函数适配器是用来修改函数行为的对象。常见的函数适配器有:
std::bind
:上述已提到,可用于部分参数绑定和函数重组。std::placeholders
:占位符,用于std::bind
中占位某些参数的位置。std::function
:用于封装可调用对象,提供了一种统一的处理方式。
示例:
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
#include <iostream>
#include <functional>
// Function object example
struct AddFunctor {
int operator()(int a, int b) const {
return a + b;
}
};
int main() {
// Using std::function with a lambda function
std::function<int(int, int)> addFunction = [](int a, int b) {
return a + b;
};
// Using std::bind to bind the first argument to 10
auto addTen = std::bind(addFunction, 10, std::placeholders::_1);
// Using a function object
AddFunctor addObj;
// Using the function object
std::cout << "Result of addObj: " << addObj(5, 3) << std::endl;
// Using std::function with std::bind
std::cout << "Result of addFunction: " << addFunction(5, 3) << std::endl;
// Using std::bind function to add 10
std::cout << "Result of addTen: " << addTen(5) << std::endl;
return 0;
}
这个示例展示了如何使用 <functional>
标准库中的函数对象和函数适配器。std::function
和 std::bind
是这个库中常用的工具,它们提供了更灵活和通用的函数操作方式。
C++ 标准库 详解
<functional>
标准库是 C++ 中提供函数对象(Function Objects)和函数适配器(Function Adapters)的头文件。这个库提供了许多功能,能够让函数像对象一样进行操作、传递和存储,以及改变函数的行为。
下面是 <functional>
标准库中一些重要的组件:
1. 函数对象(Function Objects)
函数对象是具有函数调用功能的对象,它可以像函数一样被调用。在 <functional>
中提供了以下函数对象:
-
std::function
:是一个通用的函数封装器,可以封装可调用的目标,例如函数指针、函数、成员函数、Lambda 表达式等。可以用来存储和调用各种类型的可调用对象。 -
函数对象类:程序员可以自定义函数对象类,它们是类或结构体,重载了函数调用运算符
operator()
,使得对象可以像函数一样被调用。
2. 函数适配器(Function Adapters)
函数适配器是用于修改函数行为或调整函数参数的对象。其中常见的函数适配器有:
-
std::bind
:用于创建函数对象,可以部分绑定函数或成员函数的参数。可以改变函数的参数个数或者顺序。 -
std::placeholders
:在使用std::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
#include <iostream>
#include <functional>
// 函数对象示例
struct MultiplyFunctor {
int operator()(int a, int b) const {
return a * b;
}
};
int main() {
// 使用 std::function 包装 Lambda 表达式
std::function<int(int, int)> multiplyFunction = [](int a, int b) {
return a * b;
};
// 使用 std::bind 部分绑定参数
auto multiplyByTwo = std::bind(multiplyFunction, std::placeholders::_1, 2);
// 使用自定义函数对象
MultiplyFunctor multiplyObj;
// 使用自定义函数对象
std::cout << "Result of multiplyObj: " << multiplyObj(5, 3) << std::endl;
// 使用 std::function 调用 Lambda 函数
std::cout << "Result of multiplyFunction: " << multiplyFunction(5, 3) << std::endl;
// 使用 std::bind 绑定函数的参数
std::cout << "Result of multiplyByTwo: " << multiplyByTwo(5) << std::endl;
return 0;
}
这个示例演示了如何使用 <functional>
标准库中的函数对象和函数适配器。std::function
提供了一种通用的函数封装器,std::bind
则用于创建函数对象并部分绑定参数。函数对象可以是 Lambda 表达式、函数指针或自定义的函数对象类。
C++ 标准库 常用类和函数
<functional>
标准库提供了许多有用的类和函数,使得函数能够像对象一样进行操作、传递和存储。以下是 <functional>
常用的类和函数:
1. 类
std::function
- 用于封装各种可调用对象,如函数指针、函数、成员函数、Lambda 表达式等。
- 提供了一种通用的函数封装器,能够在运行时存储和调用各种类型的可调用对象。
std::bind
- 用于创建函数对象,能够绑定函数或成员函数的参数。
- 允许指定参数的顺序、部分绑定参数或者重新组织参数,生成一个新的可调用对象。
std::placeholders
- 用于指定占位符,配合
std::bind
使用,指定未指定的参数位置。 - 提供了占位符
_1
、_2
、_3
等,用于表示绑定时未指定的参数位置。
2. 函数
算术函数:
std::plus
:加法函数对象。std::minus
:减法函数对象。std::multiplies
:乘法函数对象。std::divides
:除法函数对象。std::modulus
:取模函数对象。
逻辑函数:
std::logical_and
:逻辑与函数对象。std::logical_or
:逻辑或函数对象。std::logical_not
:逻辑非函数对象。
其他函数:
std::negate
:一元取反函数对象。std::not1
:一元谓词取反函数对象。std::not2
:二元谓词取反函数对象。
示例代码:
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
#include <iostream>
#include <functional>
// 函数对象示例
struct MultiplyFunctor {
int operator()(int a, int b) const {
return a * b;
}
};
int main() {
// 使用 std::function 封装 Lambda 表达式
std::function<int(int, int)> multiplyFunction = [](int a, int b) {
return a * b;
};
// 使用 std::bind 绑定函数对象并部分绑定参数
auto multiplyByTwo = std::bind(multiplyFunction, std::placeholders::_1, 2);
// 使用自定义函数对象
MultiplyFunctor multiplyObj;
// 使用自定义函数对象
std::cout << "Result of multiplyObj: " << multiplyObj(5, 3) << std::endl;
// 使用 std::function 调用 Lambda 函数
std::cout << "Result of multiplyFunction: " << multiplyFunction(5, 3) << std::endl;
// 使用 std::bind 绑定函数对象的参数
std::cout << "Result of multiplyByTwo: " << multiplyByTwo(5) << std::endl;
return 0;
}
这个示例展示了 <functional>
标准库中的一些常用函数和类的用法。std::function
可用于封装不同类型的可调用对象,std::bind
可用于创建函数对象并部分绑定参数,而函数对象可以是 Lambda 表达式、函数指针或自定义的函数对象类。
std::function
std::function
是 <functional>
头文件中提供的一个类模板,用于封装可调用对象(函数、函数指针、成员函数、Lambda 表达式等),并提供一种通用的函数封装器。
基本语法:
1
2
3
#include <functional>
std::function<return_type(args...)> func_object;
return_type
:函数或可调用对象返回类型。args...
:函数或可调用对象的参数类型列表。
特点和用途:
std::function
能够封装各种类型的可调用对象,提供了一种统一的处理方式。- 可以在运行时动态地指定要调用的函数或对象,从而实现动态多态性。
- 可用作函数参数、返回值或容器内的元素类型,能够实现灵活的函数传递和存储。
示例代码:
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
#include <iostream>
#include <functional>
// 函数示例
int add(int a, int b) {
return a + b;
}
int main() {
// 封装普通函数
std::function<int(int, int)> func = add;
// 封装 Lambda 表达式
std::function<int(int, int)> lambdaFunc = [](int x, int y) {
return x * y;
};
// 调用封装的普通函数
std::cout << "Result of add function: " << func(3, 4) << std::endl;
// 调用封装的 Lambda 表达式
std::cout << "Result of lambda function: " << lambdaFunc(3, 4) << std::endl;
return 0;
}
在这个示例中,std::function
分别封装了一个普通函数和一个 Lambda 表达式,并能够像函数一样调用这些封装的对象。std::function
提供了一种通用的函数封装器,能够灵活地封装各种可调用对象,并统一地调用它们。
std::bind
std::bind
是 <functional>
头文件中提供的一个函数模板,用于创建函数对象并进行参数绑定。
基本语法:
1
2
3
#include <functional>
auto func = std::bind(func_to_bind, args...);
func_to_bind
:要绑定的函数、函数指针、成员函数指针或可调用对象。args...
:要绑定的参数列表,可以包含占位符_1
,_2
,_3
等,代表未指定的参数位置。
特点和用途:
std::bind
允许对函数或函数对象进行部分参数绑定、参数重排以及参数固定等操作,生成一个新的函数对象。- 可以用来创建函数对象,将部分参数预先绑定,使得函数调用更加灵活。
- 创建了一个新的可调用对象,其参数列表为绑定参数后剩余的参数。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <functional>
// 函数示例
int add(int a, int b) {
return a + b;
}
int main() {
// 绑定参数的 add 函数
auto addFive = std::bind(add, 5, std::placeholders::_1);
// 调用绑定参数的 add 函数
std::cout << "Result of addFive function: " << addFive(3) << std::endl;
return 0;
}
在这个示例中,std::bind
绑定了一个参数为 5 的 add
函数,并将第二个参数作为占位符 _1
留待后续提供。之后创建了一个新的函数对象 addFive
,用于调用绑定了部分参数的 add
函数。std::bind
允许对函数进行部分参数绑定,生成一个新的可调用对象。
std::placeholders
std::placeholders
是 <functional>
头文件中的一个命名空间,其中定义了一系列占位符,用于在使用 std::bind
时指示参数的位置。
常用的占位符:
_1
、_2
、_3
…_n
:表示函数调用时的第一个、第二个、第三个… 第n个参数位置。
这些占位符用于 std::bind
中,协助进行参数绑定。在 std::bind
中,使用这些占位符可以指定哪些参数是预先绑定的,哪些参数需要在调用时提供。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <functional>
void printThree(int a, int b, int c) {
std::cout << a << ", " << b << ", " << c << std::endl;
}
int main() {
// 绑定函数并重新排列参数顺序
auto printFunction = std::bind(printThree, std::placeholders::_3, std::placeholders::_1, std::placeholders::_2);
// 调用绑定函数
printFunction(1, 2, 3);
return 0;
}
在这个示例中,std::placeholders
的占位符 _1
、_2
、_3
分别表示绑定的函数 printThree
的第三个、第一个和第二个参数的位置。std::bind
创建了一个新的函数对象 printFunction
,并重新排列了参数顺序。在调用 printFunction
时,参数的顺序将被重新排列以匹配绑定的函数。
std::plus
std::plus
是 <functional>
头文件中提供的函数对象,用于执行加法操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行加法操作。
基本语法:
1
2
3
#include <functional>
std::plus<T> plus_object;
T
:加法操作的参数类型。
使用方法:
std::plus
对象可以像函数一样调用,用于执行加法操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 int
、float
、double
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::plus<int> plusInt;
int result = plusInt(3, 4); // 执行加法操作
std::cout << "Result of addition: " << result << std::endl;
return 0;
}
在这个示例中,std::plus
实例化为 std::plus<int>
,表示执行整数类型的加法操作。plusInt
对象被调用并传递两个参数,执行加法操作并返回结果。
std::minus
std::minus
是 <functional>
头文件中提供的函数对象,用于执行减法操作。它也是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行减法操作。
基本语法:
1
2
3
#include <functional>
std::minus<T> minus_object;
T
:减法操作的参数类型。
使用方法:
std::minus
对象可以像函数一样调用,用于执行减法操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 int
、float
、double
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::minus<int> minusInt;
int result = minusInt(7, 4); // 执行减法操作
std::cout << "Result of subtraction: " << result << std::endl;
return 0;
}
在这个示例中,std::minus
实例化为 std::minus<int>
,表示执行整数类型的减法操作。minusInt
对象被调用并传递两个参数,执行减法操作并返回结果。
std::multiplies
std::multiplies
是 <functional>
头文件中提供的函数对象,用于执行乘法操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行乘法操作。
基本语法:
1
2
3
#include <functional>
std::multiplies<T> multiplies_object;
T
:乘法操作的参数类型。
使用方法:
std::multiplies
对象可以像函数一样调用,用于执行乘法操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 int
、float
、double
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::multiplies<int> multipliesInt;
int result = multipliesInt(3, 4); // 执行乘法操作
std::cout << "Result of multiplication: " << result << std::endl;
return 0;
}
在这个示例中,std::multiplies
实例化为 std::multiplies<int>
,表示执行整数类型的乘法操作。multipliesInt
对象被调用并传递两个参数,执行乘法操作并返回结果。
std::divides
std::divides
是 <functional>
头文件中提供的函数对象,用于执行除法操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行除法操作。
基本语法:
1
2
3
#include <functional>
std::divides<T> divides_object;
T
:除法操作的参数类型。
使用方法:
std::divides
对象可以像函数一样调用,用于执行除法操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 int
、float
、double
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::divides<double> dividesDouble;
double result = dividesDouble(10.0, 2.0); // 执行除法操作
std::cout << "Result of division: " << result << std::endl;
return 0;
}
在这个示例中,std::divides
实例化为 std::divides<double>
,表示执行双精度浮点数类型的除法操作。dividesDouble
对象被调用并传递两个参数,执行除法操作并返回结果。
std::modulus
std::modulus
是 <functional>
头文件中提供的函数对象,用于执行取模(取余)操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行取模操作。
基本语法:
1
2
3
#include <functional>
std::modulus<T> modulus_object;
T
:取模操作的参数类型。
使用方法:
std::modulus
对象可以像函数一样调用,用于执行取模操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 int
、float
、double
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::modulus<int> modulusInt;
int result = modulusInt(10, 3); // 执行取模操作
std::cout << "Result of modulus: " << result << std::endl;
return 0;
}
在这个示例中,std::modulus
实例化为 std::modulus<int>
,表示执行整数类型的取模操作。modulusInt
对象被调用并传递两个参数,执行取模操作并返回结果。
std::logical_and
std::logical_and
是 <functional>
头文件中提供的函数对象,用于执行逻辑与操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行逻辑与操作。
基本语法:
1
2
3
#include <functional>
std::logical_and<T> logical_and_object;
T
:逻辑与操作的参数类型。
使用方法:
std::logical_and
对象可以像函数一样调用,用于执行逻辑与操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 bool
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::logical_and<bool> logicalAndBool;
bool result = logicalAndBool(true, false); // 执行逻辑与操作
std::cout << "Result of logical AND: " << std::boolalpha << result << std::endl;
return 0;
}
在这个示例中,std::logical_and
实例化为 std::logical_and<bool>
,表示执行布尔类型的逻辑与操作。logicalAndBool
对象被调用并传递两个参数,执行逻辑与操作并返回结果。
std::logical_or
std::logical_or
是 <functional>
头文件中提供的函数对象,用于执行逻辑或操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行逻辑或操作。
基本语法:
1
2
3
#include <functional>
std::logical_or<T> logical_or_object;
T
:逻辑或操作的参数类型。
使用方法:
std::logical_or
对象可以像函数一样调用,用于执行逻辑或操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 bool
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::logical_or<bool> logicalOrBool;
bool result = logicalOrBool(true, false); // 执行逻辑或操作
std::cout << "Result of logical OR: " << std::boolalpha << result << std::endl;
return 0;
}
在这个示例中,std::logical_or
实例化为 std::logical_or<bool>
,表示执行布尔类型的逻辑或操作。logicalOrBool
对象被调用并传递两个参数,执行逻辑或操作并返回结果。
std::logical_not
std::logical_not
是 <functional>
头文件中提供的函数对象,用于执行逻辑非(取反)操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行逻辑非操作。
基本语法:
1
2
3
#include <functional>
std::logical_not<T> logical_not_object;
T
:逻辑非操作的参数类型。
使用方法:
std::logical_not
对象可以像函数一样调用,用于执行逻辑非操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 bool
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::logical_not<bool> logicalNotBool;
bool result = logicalNotBool(true); // 执行逻辑非操作
std::cout << "Result of logical NOT: " << std::boolalpha << result << std::endl;
return 0;
}
在这个示例中,std::logical_not
实例化为 std::logical_not<bool>
,表示执行布尔类型的逻辑非操作。logicalNotBool
对象被调用并传递一个参数,执行逻辑非操作并返回结果。
std::negate
std::negate
是 <functional>
头文件中提供的函数对象,用于执行一元取反操作。它是一个函数对象类,重载了函数调用运算符 operator()
,使其能够执行一元取反操作。
基本语法:
1
2
3
#include <functional>
std::negate<T> negate_object;
T
:取反操作的参数类型。
使用方法:
std::negate
对象可以像函数一样调用,用于执行一元取反操作。它是一个模板类,可以根据需要指定不同的参数类型,比如 int
、float
、double
等。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <functional>
int main() {
std::negate<int> negateInt;
int result = negateInt(10); // 执行一元取反操作
std::cout << "Result of unary negation: " << result << std::endl;
return 0;
}
在这个示例中,std::negate
实例化为 std::negate<int>
,表示执行整数类型的一元取反操作。negateInt
对象被调用并传递一个参数,执行一元取反操作并返回结果。
std::not1
std::not1
是 <functional>
头文件中提供的函数对象适配器,用于对一元谓词函数进行取反操作。它可用于构造一个函数对象,将传入的一元谓词函数对象的结果进行取反。
基本语法:
1
2
3
#include <functional>
std::not1<UnaryPredicate> not1_object;
UnaryPredicate
:一元谓词函数对象类型。
使用方法:
std::not1
可以用于对一元谓词函数对象进行取反操作。它接受一个一元谓词函数对象作为参数,并返回一个新的谓词函数对象,该对象对传入的谓词函数的返回值进行取反。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <functional>
bool greaterThanThree(int x) {
return x > 3;
}
int main() {
std::function<bool(int)> pred = std::not1<std::function<bool(int)>>(greaterThanThree);
std::cout << "Result of not1: " << std::boolalpha << pred(4) << std::endl; // Result will be false
return 0;
}
在这个示例中,std::not1
对 greaterThanThree
函数对象进行取反操作。pred
对象被调用并传递一个参数,返回结果为传入参数的一元谓词函数的取反结果。
std::not2
std::not2
是 <functional>
头文件中提供的函数对象适配器,用于对二元谓词函数进行取反操作。它可用于构造一个函数对象,将传入的二元谓词函数对象的结果进行取反。
基本语法:
1
2
3
#include <functional>
std::not2<BinaryPredicate> not2_object;
BinaryPredicate
:二元谓词函数对象类型。
使用方法:
std::not2
可以用于对二元谓词函数对象进行取反操作。它接受一个二元谓词函数对象作为参数,并返回一个新的谓词函数对象,该对象对传入的谓词函数的返回值进行取反。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <functional>
bool lessThanOrEqual(int x, int y) {
return x <= y;
}
int main() {
std::function<bool(int, int)> pred = std::not2<std::function<bool(int, int)>>(lessThanOrEqual);
std::cout << "Result of not2: " << std::boolalpha << pred(4, 3) << std::endl; // Result will be false
return 0;
}
在这个示例中,std::not2
对 lessThanOrEqual
函数对象进行取反操作。pred
对象被调用并传递两个参数,返回结果为传入参数的二元谓词函数的取反结果。