电商网站模版,自己建网站怎么建,企业网站 案例,dede网站优化适配器概述
C标准模板库(STL)中提供了几种适配器#xff0c;这些适配器主要用于修改或扩展容器类的功能。STL中的适配器主要包括以下几种#xff1a;
1、迭代器适配器#xff1a;迭代器适配器提供了一种机制#xff0c;可以将非迭代器对象转换为迭代器对象。比如back_ins…适配器概述
C标准模板库(STL)中提供了几种适配器这些适配器主要用于修改或扩展容器类的功能。STL中的适配器主要包括以下几种
1、迭代器适配器迭代器适配器提供了一种机制可以将非迭代器对象转换为迭代器对象。比如back_insert_iterator和front_insert_iterator这两个迭代器适配器分别提供了在容器的末尾和开头插入元素的功能。
2、函数对象适配器函数对象适配器是一种通用机制它为任何满足函数对象需求的对象提供了一个接口。这包括函数调用适配器如binder1st和binder2nd这些适配器可以将二元操作符转换为单目操作符以及函数对象适配器如unary_function和binary_function这些适配器为函数对象提供了统一的接口。
3、流适配器流适配器允许你将流包装在其他流中从而改变或扩展其行为。例如stringstream可以用于将字符串作为输入或输出流。
4、容器适配器容器适配器提供了一种机制可以修改或扩展容器的行为。例如stack和queue就是容器适配器它们分别提供了栈和队列的数据结构。
这些适配器为C程序员提供了强大的工具使他们能够以灵活的方式使用STL容器和算法。
容器适配器
C标准模板库(STL)中的容器适配器是一种特殊类型的容器它们为特定的STL容器提供了一种包装器允许以不同的方式使用这些容器。容器适配器提供了一种机制可以修改或扩展容器的行为以满足特定的需求。
容器适配器主要有以下几种 1、栈stack适配器栈是一种后进先出LIFO的数据结构只能在一端称为栈顶进行插入和删除操作。STL中的stack适配器提供了一个基于栈的容器它提供了在栈顶插入和删除元素的操作。stack适配器提供了一个push方法用于在栈顶插入元素一个pop方法用于删除栈顶元素以及一个top方法用于获取栈顶元素。 2、队列queue适配器队列是一种先进先出FIFO的数据结构只能在一端插入元素在另一端删除元素。STL中的queue适配器提供了一个基于队列的容器它提供了在队列尾部插入元素和从队列头部删除元素的操作。queue适配器提供了两个方法push用于在队列尾部插入元素pop用于删除队列头部元素。 3、优先队列priority_queue适配器优先队列是一种数据结构其中元素具有优先级优先级最高的元素总是位于队列的顶部。STL中的priority_queue适配器提供了一个基于优先队列的容器它允许你指定一个比较函数或函数对象用于确定元素的优先级。priority_queue适配器提供了两个方法push用于向队列中插入元素pop用于删除优先级最高的元素。 这些容器适配器为C程序员提供了一种方便的方式来使用STL容器而无需编写大量的代码来手动实现这些数据结构的行为。通过使用容器适配器我们可以更轻松地处理特定类型的数据并利用STL提供的强大功能来处理这些数据。
栈(stack)适配器
C标准模板库STL中的栈容器适配器是一个封装了底层容器行为使其符合栈数据结构操作的特殊容器。栈是一种后进先出LIFO的数据结构只能在一端称为栈顶进行插入和删除操作。
栈容器适配器提供了一种方便的方式来使用STL中的容器同时保持栈的特性。它提供了一组与栈操作相对应的方法用于在栈顶插入和删除元素。下面是关于C STL中栈容器适配器的详细介绍
基本操作 push在栈顶插入一个元素。 pop删除栈顶元素。 top获取栈顶元素但不删除。 empty检查栈是否为空。 使用方式
#include stack
#include iostream int main() { std::stackint myStack; // 向栈中压入元素 myStack.push(10); myStack.push(20); myStack.push(30); // 输出栈顶元素 std::cout 栈顶元素: myStack.top() std::endl; // 弹出栈顶元素并输出 while (!myStack.empty()) { std::cout 弹出的元素: myStack.top() std::endl; myStack.pop(); } return 0;
}底层容器栈容器适配器底层可以使用任何STL容器作为其存储机制如vector、deque等。默认情况下std::stack使用std::vector作为底层容器。你可以通过构造函数或成员函数来指定底层容器的类型。例如std::stackint, std::deque myStack;使用deque作为底层容器。
异常处理在进行插入和删除操作时如果底层容器无法满足需求例如空间不足栈容器适配器会抛出相应的异常。你可以通过捕获异常来处理这些错误情况。
自定义比较函数在某些情况下你可能希望根据自定义的比较函数来确定元素的优先级。你可以通过向std::priority_queue提供自定义的比较函数或函数对象来实现这一点。同样栈容器适配器也可以使用类似的机制来控制元素的排序行为。
关联容器除了基础的栈操作STL还提供了关联容器如std::map和std::set它们本质上也是基于栈的适配器但提供了更复杂的操作和语义。这些关联容器允许你根据键值对进行插入、删除和查找操作同时保持元素的顺序。
总的来说C STL中的栈容器适配器提供了一种高效的方式来使用STL容器来模拟栈数据结构的行为。通过使用这些适配器我们可以更方便地处理特定类型的数据并利用STL提供的强大功能来处理这些数据。
队列(queue)适配器
C标准模板库STL中的队列容器适配器是一个封装了底层容器行为使其符合队列数据结构操作的特殊容器。队列是一种先进先出FIFO的数据结构只能在一端插入元素在另一端删除元素。
队列容器适配器提供了一种方便的方式来使用STL中的容器同时保持队列的特性。它提供了一组与队列操作相对应的方法用于在队列尾部插入元素和从队列头部删除元素。下面是关于C STL中队列容器适配器的详细介绍
基本操作 push在队列尾部插入一个元素。 pop删除队列头部元素。 front获取队列头部元素但不删除。 back获取队列尾部元素但不删除。 empty检查队列是否为空。 使用方式
#include queue
#include iostream int main() { std::queueint myQueue; // 向队列中插入元素 myQueue.push(10); myQueue.push(20); myQueue.push(30); // 输出队列头部元素 std::cout 队列头部元素: myQueue.front() std::endl; // 弹出队列头部元素并输出 while (!myQueue.empty()) { std::cout 弹出的元素: myQueue.front() std::endl; myQueue.pop(); } return 0;
}底层容器队列容器适配器底层可以使用任何STL容器作为其存储机制如vector、deque等。默认情况下std::queue使用std::deque作为底层容器。我们可以通过构造函数或成员函数来指定底层容器的类型。例如std::queueint, std::vector myQueue;使用vector作为底层容器。
异常处理在进行插入和删除操作时如果底层容器无法满足需求例如空间不足队列容器适配器会抛出相应的异常。我们可以通过捕获异常来处理这些错误情况。
自定义比较函数类似于栈容器适配器我们也可以通过提供自定义的比较函数或函数对象来控制队列中元素的排序行为。这对于实现优先队列等高级数据结构非常有用。
关联容器除了基础的队列操作STL还提供了关联容器如std::map和std::set它们本质上也是基于队列的适配器但提供了更复杂的操作和语义。这些关联容器允许你根据键值对进行插入、删除和查找操作同时保持元素的顺序。
总的来说C STL中的队列容器适配器提供了一种高效的方式来使用STL容器来模拟队列数据结构的行为。通过使用这些适配器我们可以更方便地处理特定类型的数据并利用STL提供的强大功能来处理这些数据。
优先队列priority_queue适配器
#include functional
#include iostream
#include queue
#include vectorusing namespace std;void test(){//原理优先级队列底层使用的是大根堆大顶堆。//当将元素存到优先级队列后会按照std::less的标准进行排序当//只有一个元素的时候优先级最高的就是该元素该元素会放在堆顶//当有新的元素插入进来之后此时会与堆顶进行比较如果堆顶小于//插入进来的元素此时就满足std::less就会将新的元素与堆顶进行//置换新的元素成为新的堆顶如果新插入的元素与堆顶进行比较//发现堆顶大于等于新插入的元素此时不满足std::less那么老的堆顶//依旧是新的堆顶不会发生置换//创建优先级对象//对于优先级对象来说其无法使用大括号形式进行初始化//可以使用迭代器范围的方式进行初始化vectorint vec {1,5,6,7,3};//priority_queueint number(vec.begin(),vec.end());//使用追加方式进行初始化//priority_queueint pque; 默认是升序即值大的优先级最高priority_queueint,vectorint,greaterint pque;//改变默认方式使其按降序排优先级//与之前学习容器的内容一样若是自定义类型那么就需要手动实现一下其优先的规则//实现一个compare类或者函数即可for(size_t idx0; idx ! vec.size();idx){pque.push(vec[idx]);cout 优先级最高的元素 pque.top() endl;}//优先级队列的遍历while(!pque.empty()){cout pque.top() ;pque.top();}
}int main(){test();return 0;
}
函数对象适配器
这一部分主要讲bind_first 和 bind_second。
bind_first 和 bind_second 是 C Standard Template Library (STL) 中的两个函数对象适配器它们用于将二元函数对象绑定到特定的第一个和第二个参数。这两个函数对象在 STL 的 头文件中定义。
bind_first
bind_first 用于绑定二元函数对象的第一个参数。它的作用是将二元函数对象的第一个参数绑定到一个特定的值然后返回一个新的一元函数对象该对象在调用时将使用绑定的值作为其参数。
函数原型如下
template class BinaryFunction, class T BinaryFunction bind_first(const BinaryFunction f, const T x);
参数说明 f要绑定的二元函数对象。 x要绑定为二元函数对象第一个参数的值。 返回值返回一个新的一元函数对象该对象在调用时将使用绑定的值作为其参数。
bind_second
bind_second 用于绑定二元函数对象的第二个参数。它的作用是将二元函数对象的第二个参数绑定到一个特定的值然后返回一个新的一元函数对象该对象在调用时将使用绑定的值作为其参数。
函数原型如下
template class BinaryFunction, class T BinaryFunction bind_second(const BinaryFunction f, const T x);参数说明 f要绑定的二元函数对象。 x要绑定为二元函数对象第二个参数的值。 返回值返回一个新的一元函数对象该对象在调用时将使用绑定的值作为其参数。
bind_first与bind_second示例
假设我们有一个二元函数对象 Add它用于将两个数相加。我们可以使用 bind_first 和 bind_second 来创建一个新的一元函数对象该对象将一个特定的数作为参数并返回两个固定数之和。
#include iostream
#include functional // for bind_first and bind_second // 定义一个二元函数对象用于将两个数相加
struct Add { int operator()(int a, int b) const { return a b; }
}; int main() { Add add; // 二元函数对象用于相加 // 使用 bind_first 绑定第一个参数为 5创建一个新的一元函数对象 std::functionint(int) add5 std::bind_first(add, 5); std::cout add5(3) std::endl; // 输出8因为 5 3 8 // 使用 bind_second 绑定第二个参数为 10创建一个新的一元函数对象 std::functionint(int) add10 std::bind_second(add, 10); std::cout add10(2) std::endl; // 输出12因为 2 10 12 return 0;
}在这个例子中我们使用 bind_first 将第一个参数绑定为 5然后创建了一个新的一元函数对象 add5。这个新函数对象接受一个参数并返回 5 与该参数的和。类似地我们使用 bind_second 将第二个参数绑定为 10创建了另一个新的一元函数对象 add10。这个新函数对象接受一个参数并返回该参数与 10 的和。
bind
前面说的bind_first与bind_second都太死板了bind是更为灵活的一个函数的对象适配器。
std::bind 是 C Standard Template Library (STL) 中的一个非常有用的函数它用于绑定一个函数或可调用对象到一个或多个参数上从而创建一个新的可调用对象。
函数原型如下
template class F, class... BoundArgs constexpr auto bind(F f, BoundArgs... args) - typename std::bind_helpertypename std::is_bind_expressionF::type, F, BoundArgs...::type;参数说明 f要绑定的函数或可调用对象。 args要绑定到函数或可调用对象的参数。 返回值返回一个新的一元函数对象该对象在调用时将使用绑定的参数作为其参数。
bind示例
假设我们有一个函数 gcd用于计算两个数的最大公约数。我们想创建一个新的函数该函数接受一个参数并返回两个固定数例如42和56的最大公约数。
#include iostream
#include functional // for std::bind // 定义一个函数用于计算两个数的最大公约数
int gcd(int a, int b) { return b 0 ? a : gcd(b, a % b);
} int main() { // 使用 std::bind 创建一个新函数该函数接受一个参数并返回 42 和 56 的最大公约数 std::functionint(int) gcdFixed std::bind(gcd, 42, 56); std::cout gcdFixed(14) std::endl; // 输出2因为 42 和 56 的最大公约数是 2并且 14 可以被 2 整除 return 0;
}在这个例子中我们使用 std::bind 将 gcd 函数绑定到两个固定的参数 42 和 56然后创建了一个新的函数对象 gcdFixed。这个新函数对象接受一个参数并返回 42 和 56 的最大公约数。通过这种方式我们可以轻松地创建一个新的函数对象该对象执行特定的操作并返回固定的结果。
成员函数适配器成员函数绑定器mem_fn
std::mem_fn 是 C Standard Template Library (STL) 中的成员函数绑定器它提供了一种便捷的方式来绑定成员函数到一个特定的对象实例并创建一个新的可调用对象。std::mem_fn 主要用于绑定非静态成员函数。
std::mem_fn 的原型如下
template class T
class mem_fn;使用 std::mem_fn 的方式是通过 std::mem_fn(object, member_function) 来创建新的可调用对象其中 object 是包含成员函数的类的实例而 member_function 是要绑定的成员函数名。
以下是一个使用 std::mem_fn 的示例
#include iostream
#include functional // for std::mem_fn
#include vector class MyClass {
public: int myMemberFunction(int value) { return value * 2; }
}; int main() { MyClass obj; std::vectorstd::functionint() callbacks; // 使用 std::mem_fn 绑定成员函数和对象实例 //在C语言中函数名字是函数的入口地址C语言是不支持函数重载的//而在C中因为存在函数重载要找到函数可以使用函数进行取地址add;C是兼容C语言,所以普通//函数的函数名就是函数的入口地址但是C中成员函数的函数名字就不是函数的入口地址所以需要像下面这样写。auto callback std::mem_fn(MyClass::myMemberFunction, obj); // 将回调添加到向量中 callbacks.push_back(callback); // 调用回调函数并获取结果 for (const auto func : callbacks) { int result func(); // 输出84因为 42 * 2 84 std::cout Result: result std::endl; } return 0;
}
在这个示例中我们创建了一个 MyClass 的对象 obj并使用 std::mem_fn 将其成员函数 myMemberFunction 绑定到该对象实例上。通过这种方式我们创建了一个新的可调用对象 callback它可以在稍后被调用。我们将这个回调添加到一个向量中并在循环中调用它从而演示了 std::mem_fn 的用法。需要注意的是使用 std::mem_fn 时需要包含类的对象来调用绑定的成员函数。
函数包装器function
std::function 是 C Standard Template Library (STL) 中的一个通用、多态的函数包装器。它是一个类型安全的解决方案用于存储、复制和调用任何 Callable 目标函数、lambda 表达式、bind 表达式或任何其他可调用对象。
std::function 的主要用途包括 回调和事件处理在许多情况下我们可能需要将一个函数或可调用对象作为参数传递给其他函数或存储为某个对象的状态。使用 std::function 可以简化这个过程使其更加类型安全。 组合和链式调用通过将函数或可调用对象存储在 std::function 对象中我们可以轻松地与其他函数或方法组合使用实现链式调用。 实现回调和观察者模式在回调机制和观察者模式中经常需要将函数或可调用对象作为参数传递给其他对象或组件。std::function 可以简化这个过程。 std::function 的声明语法如下
std::function返回类型(参数列表)其中返回类型和参数列表指定了 std::function 所持有的 Callable 目标的签名。
下面是一个简单的 std::function 使用示例
#include iostream
#include functional // for std::function
#include vector // 声明一个 std::function 对象用于存储可调用对象
std::functionint(int) f; // 定义一个可调用对象函数或 lambda 表达式
int add(int a, int b) { return a b;
} int main() { // 将函数赋值给 std::function 对象 f add; // 调用 std::function 对象并获取结果 int result f(42, 56); // 输出98因为 42 56 98 std::cout Result: result std::endl; // 使用 lambda 表达式赋值给 std::function 对象 f [](int a, int b) { return a * b; }; result f(42, 56); // 输出2352因为 42 * 56 2352 std::cout Result: result std::endl; return 0;
}在这个示例中我们声明了一个 std::function 对象 f并使用函数 add 和 lambda 表达式来赋值给它。然后我们可以通过 f 来调用这些可调用对象并获取返回的结果。注意std::function 可以持有任何可调用对象包括函数、lambda 表达式、bind 表达式或其他任何可调用对象。
迭代器概述
迭代器是一种设计模式用于遍历容器中的元素而不需要知道容器的底层表示方式。
C标准模板库STL中的迭代器允许程序员通过迭代器来访问和操作容器中的元素而不是直接使用指针。
迭代器具有以下特性 1、双向访问迭代器允许你通过和–运算符向前或向后遍历容器中的元素。 2、随机访问某些迭代器如std::vector::iterator还允许你通过索引操作符[]直接访问特定位置的元素。 3、关联容器关联容器如std::map和std::set的迭代器通常也支持基于键的访问。 4、多态迭代器多态迭代器可以指向不同类型的容器只要它们都满足一定的接口要求。 迭代器的主要用途包括 1、遍历容器使用迭代器可以方便地遍历容器中的所有元素。例如for循环结合迭代器可以用来遍历一个容器。 2、算法通用化通过接受迭代器作为参数STL算法可以在不同的容器上使用从而提供更大的灵活性。 3、算法复用由于算法只需要知道迭代器的接口而不需要关心底层容器的实现细节这有助于代码复用和减少重复的代码。 4、泛型编程迭代器提供了一种通用的方式来处理不同类型的容器使得算法可以在不同的数据结构上工作从而实现更高级别的抽象和复用。 C STL提供了多种类型的迭代器包括输入迭代器、前向迭代器、双向迭代器和随机访问迭代器。 1、输入迭代器这是最简单的迭代器类型它只支持前向遍历且只能读取元素不能修改元素。这种迭代器常用于需要读取元素但不需要修改元素的操作。 2、前向迭代器与输入迭代器类似前向迭代器也只支持前向遍历但它可以修改元素。这意味着前向迭代器可以用于读取和修改元素的操作。 3、双向迭代器双向迭代器既可以向前也可以向后遍历元素。这种迭代器通常用于需要在两个方向上遍历元素的操作。 4、随机访问迭代器随机访问迭代器支持快速随机访问容器中的任意元素无论是向前还是向后。这种迭代器通常用于需要高效访问和修改元素的操作如排序、查找等。 这些不同类型的迭代器提供了不同程度的访问和遍历能力以满足不同的需求。
例如std::vector::iterator是一个随机访问迭代器它允许你以任意顺序访问容器中的元素。而std::list::iterator则是一个双向迭代器只能顺序遍历元素不支持随机访问。
总之C STL中的迭代器提供了一种强大而灵活的工具用于遍历和操作容器中的元素。通过使用迭代器程序员可以编写更加通用和可复用的代码以适应不同的数据结构和算法需求。
流迭代器
C标准模板库STL中的流迭代器是一种特殊的迭代器用于处理输入流和输出流的数据。流迭代器允许程序员使用迭代器的方式来处理输入流或输出流中的数据类似于处理容器中的数据。
流迭代器的主要用途是将数据从输入流中读取到容器中或将数据从容器中写入到输出流中。通过使用流迭代器程序员可以以一致的方式处理输入和输出流并利用STL提供的算法和容器进行操作。
流迭代器的工作原理 流迭代器通过包装输入流或输出流的指针来工作。它提供了一组类似于迭代器的操作如、–、*等以便程序员可以像处理容器中的元素一样处理流中的数据。 流迭代器的种类 istream_iterator用于从输入流中读取数据的迭代器。它通常与输入流如std::cin一起使用以从标准输入中读取数据。 ostream_iterator用于向输出流中写入数据的迭代器。它通常与输出流如std::cout一起使用以将数据写入标准输出。 如何使用流迭代器 使用流迭代器通常涉及以下步骤 创建一个流迭代器对象并传递要使用的输入流或输出流的指针。 使用迭代器来读取或写入数据。例如可以使用操作符来逐个读取输入流中的元素或使用*操作符来向输出流中写入元素。 在完成操作后记得关闭流迭代器或相应的输入/输出流。 下面是一个使用istream_iterator和ostream_iterator从标准输入读取数据和从标准输出输出数据的示例
void test()
{vectorint numbers{1, 2, 3, 4, 5};ostream_iteratorint osi(cout, \n);copy(numbers.begin(), numbers.end(), osi);//copy是算法库algorithm中的一个函数
}void test()
{vectorint numbers;cout 111 endl;istream_iteratorint isi(cin);cout 222 endl;/* copy(isi, istream_iteratorint(), numbers.begin());//对于vector插入元素应该调用push_back */copy(isi, istream_iteratorint(), std::back_inserter(numbers));//插入迭代器cout 333 endl;copy(numbers.begin(), numbers.end(), ostream_iteratorint(cout ,\n));
}算法概述
算法中包含很多对容器进行处理的算法使用迭代器来标识要处理的数据或数据段、以及结果的存放位 置有的函数还作为对象参数传递给另一个函数实现数据的处理。
这些算法可以操作在多种容器类型上,所以称为“泛型”泛型算法不是针对容器编写而只是单独依赖迭 代器和迭代器操作实现。
这些算法都位于下面的头文件中
#include algorithm //泛型算法
#include numeric //泛化的算术算法算法类型
1、非修改式的算法 count、find、find_xxx、for_each
2、修改式的算法 copy、remove、remove_if、unique、fill
3、排序算法 sort以及sort相关、lower_bound、upper_bound、binary_search
4、集合操作 set_intersection
5、heap的操作 make_heap、push_heap、pop_heap
6、最大值与最小值 min、max
7、比较函数 equal
8、当空间的申请与对象的构建分开的时候可以uninitialized_copy未初始化拷贝操作uninitialized_xxx
因为这些不用肯定就会忘的所以只挑几个比较具有代表性的学习一下其它的后面随用随查就是了。
函数类型
一元函数UnaryFunction函数的参数只有一个。
一元断言/一元谓词UnaryPredicate函数的参数只有一个并且函数的返回类型是bool。
二元函数函数的参数有两个。
n元函数函数的参数有n个。
for_each、count 以及 find
重点提一下for_each的算法原型如下
template class _InputIter, class _Function
_Function for_each(_InputIter __first, _InputIter __last, _Function __f)
{for ( ; __first ! __last; __first)__f(*__first);//print(*__first)return __f;
}对着测试代码很容易看出来其代码原型的逻辑测试代码如下
#include iostream
#include algorithm
#include vector
#include iteratorusing namespace std;//for_each的一元打印函数
void print(int value){cout value ;
}void test(){//想去将vector进行遍历vectorint number {1,6,8,4,2,7,9};copy(number.begin(),number.end(),ostream_iteratorint(cout, ));cout endl;//使用for_each进行遍历的时候第三个参数需要我们自己手动实现一个一元函数//然后for_each会根据这个函数来进行打印for_each(number.begin(),number.end(),print);cout endl;//传函数时也可以使用匿名函数匿名函数也就是lambda表达式//前面加个[]是语法要求没有为什么然后(int value)是参数列表//最后跟大括号写上函数体,-后面跟函数的返回值类型for_each(number.begin(),number.end(),[](int value)-void{value;cout value ;});cout endl;
}void test2(){//count的使用vectorint number {1,2,5,5,2,3,6};size_t cnt count(number.begin(),number.end(),3);cout cnt cnt endl;//find的使用auto it find(number.begin(),number.end(),5);if(it number.end()){cout 该元素不存在 endl;}else{cout 该元素存在 endl;}
}int main(){test();return 0;
}
copy
STL中的copy函数是一个通用算法用于将一个序列源范围中的元素复制到另一个序列目标范围中。这个函数在 头文件中定义。
函数原型如下
template class InputIterator, class OutputIterator OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);参数说明 first 和 last这两个参数定义了源范围的开始和结束通常是一个迭代器对。 result这个参数定义了目标范围的开始位置即元素应该复制到的位置。 返回值返回目标范围的末尾的下一个位置的迭代器。 使用示例
#include iostream
#include vector
#include algorithm int main() { std::vectorint src {1, 2, 3, 4, 5}; std::vectorint dst(src.size()); std::copy(src.begin(), src.end(), dst.begin()); for (int i : dst) { std::cout i ; } std::cout std::endl; return 0;
}
输出1 2 3 4 5
注意copy函数不会检查目标范围是否足够大以容纳源序列的所有元素。因此在使用此函数时必须确保目标范围有足够的空间来容纳源序列的所有元素以防止缓冲区溢出。如果需要将元素复制到已分配的空间之外可以使用std::copy_n函数。
remove_if
remove_if 是 C Standard Template Library (STL) 中的一个非常有用的算法用于从容器中删除满足特定条件的元素。这个函数返回一个迭代器指向第一个被删除元素之后的位置。
函数原型如下
template class BidirIt, class UnaryPredicate
BidirIt remove_if (BidirIt first, BidirIt last, UnaryPredicate p);参数说明 first 和 last这两个参数定义了要处理的序列的开始和结束。 p这是一个一元谓词它接受一个元素并返回一个布尔值如果元素满足条件即返回 true则该元素被删除否则保留。 返回值返回指向第一个被删除元素之后的位置的迭代器。 使用示例
#include iostream
#include vector
#include algorithm
#include functional // for std::not_equal_to int main() { std::vectorint v {1, 2, 3, 4, 5, 6}; auto it std::remove_if(v.begin(), v.end(), [](int i){ return i % 2 0; }); // 删除所有偶数 v.erase(it, v.end()); // 删除所有满足条件的元素 for (int i : v) { std::cout i ; } std::cout std::endl; return 0;
}输出1 3 5
在这个例子中我们使用了 lambda 函数 [](int i){ return i % 2 0;} 来检查一个数字是否是偶数。remove_if 将所有偶数移动到容器的前面并返回一个指向第一个被删除元素之后的位置的迭代器。然后我们使用 erase 方法删除这些元素。结果是容器中只剩下奇数。
使用remove_if的时候需要注意remove_if不会将满足条件的数据删除但是会返回待删除元素的首地址(或者说首迭代器)然后再配合erase函数使用即可。