当前位置: 首页 > news >正文

C++11: STL之bind

C++11: STL之bind

  • 引言
  • 可调用对象的绑定
    • 绑定普通函数
    • 绑定静态函数
    • 绑定类成员函数
    • 绑定仿函数
    • 绑定Lambda
  • 占位符std::placeholders的应用
    • 嵌套绑定
    • 参数重排序
    • 结合 STL 算法
    • 占位符传递到嵌套函数
    • 混合占位符与默认值
    • 复杂占位符组合
  • std::bind的原理
    • std::bind 的设计思路
    • 简化实现示例
  • Bind的陷阱
  • 总结

引言

std::bind 是 C++11 引入的一种函数适配器,能够将一个可调用对象(如函数、成员函数、仿函数或 lambda 表达式)与其支持的部分(或全部)参数绑定生成一个新的可调用对象。基于std::bind,开发者可调整目标函数的参数列表顺序或绑定部分参数,这极大地增强了函数调用的灵活性。

std::bind 的函数声明位于头文件 ,其形式如下:

template< class F, class... Args > 
/* unspecified */ bind( F&& f, Args&&... args );template< class R, class F, class... Args >
/* unspecified */ bind( F&& f, Args&&... args );

参数说明:
• F: 可调用对象(普通函数、静态函数、类成员函数、仿函数或 lambda)。
• Args: 要绑定的参数列表。可以传递具体值或占位符 std::placeholders::_1, std::placeholders::_2, … (表示待传入的参数)。

可调用对象的绑定

Bind可支持普通函数、静态函数、类成员函数、仿函数或 lambda等多种可以调用对象的绑定。

绑定普通函数

对于普通函数,我们可以直接利用 std::bind 绑定部分参数,进而生成一个新的可调用对象。例如:

#include <iostream>
#include <functional>void printMessage(const std::string& message, int repeatCount) 
{for (int i = 0; i < repeatCount; ++i){std::cout << message << std::endl;}
}int main() 
{auto bindPrintMessage = std::bind(printMessage, "Hello, World!", 3);bindPrintMessage(); // 输出三行 "Hello, World!"return 0;
}

绑定静态函数

静态成员函数与普通函数在绑定方式上较为相似,可以直接进行绑定操作。

#include <iostream>
#include <functional>class Logger 
{
public:static void logInfo(const std::string& message) {std::cout << "[INFO]: " << message << std::endl;}
};int main() 
{auto bindLogInfo = std::bind(&Logger::logInfo, "Application started");bindLogInfo(); // 输出: [INFO]: Application startedreturn 0;
}

绑定类成员函数

当绑定类的成员函数时,需要额外传递对象实例的指针作为绑定的一部分。

#include <iostream>
#include <functional>class Calculator 
{
public:void add(int a, int b) const {std::cout << "Sum: " << (a + b) << std::endl;}
};int main() 
{Calculator calculator;auto bindAdd = std::bind(&Calculator::add, &calculator, 5, 7);bindAdd(); // 输出: Sum: 12return 0;
}

绑定仿函数

仿函数是通过重载 operator() 实现的对象行为,亦可以与 std::bind 结合。

#include <iostream>
#include <functional>struct Multiply 
{void operator()(int a, int b) const {std::cout << "Product: " << (a * b) << std::endl;}
};int main() 
{Multiply multiply;auto bindMultiply = std::bind(multiply, 4, 5);bindMultiply(); // 输出: Product: 20return 0;
}

绑定Lambda

std::bind 也可以绑定 lambda 表达式,这种方式很灵活。

#include <iostream>
#include <functional>int main() 
{auto divide = [](double a, double b) {if (b != 0) {std::cout << "Result: " << (a / b) << std::endl;} else {std::cout << "Error: Division by zero!" << std::endl;}};auto bindDivide = std::bind(divide, 10.0, 2.0);bindDivide(); // 输出: Result: 5return 0;
}

占位符std::placeholders的应用

std::placeholders 是 std::bind 中的重要组成部分,允许用户在绑定函数时动态指定参数位置、调整参数顺序或实现嵌套绑定。通过使用std::placeholders::_1, std::placeholders::_2 等占位符,可以构建灵活的函数调用方式,尤其适合处理动态输入和函数组合逻辑。

嵌套绑定

使用 std::bind将一个函数绑定为另一个函数的参数,我们称之为嵌套绑定。

#include <iostream>
#include <functional>void multiplyAndPrint(int a, int b) 
{std::cout << "Product: " << (a * b) << std::endl;
}void wrapperFunction(std::function<void(int)> func, int value) 
{func(value);
}int main() 
{// 绑定 multiplyAndPrint 的第一个参数为 5,第二个参数为动态传递的值auto multiplyByFive = std::bind(multiplyAndPrint, 5, std::placeholders::_1);// 绑定 wrapperFunction,将 multiplyByFive 作为其固定参数auto bindWrapper = std::bind(wrapperFunction, multiplyByFive, std::placeholders::_1);// 动态传递参数bindWrapper(10); // 输出: Product: 50return 0;
}

参数重排序

通过占位符调整参数的传递顺序。

#include <iostream>
#include <functional>void calculate(int a, int b, int c) 
{std::cout << "Result: " << (a + b * c) << std::endl;
}int main() 
{// 调整参数顺序://  1. std::placeholders::_3表示将调用的第二个参数传递给binder的第三个参数,//  2. std::placeholders::_2表示将调用的第三个参数传递给binder的第二个参数auto reorderedCalculate = std::bind(calculate, std::placeholders::_1, std::placeholders::_3, std::placeholders::_2);reorderedCalculate(2, 3, 4); // 实际调用: calculate(2, 4, 3),输出: Result: 14return 0;
}

结合 STL 算法

将 std::bind 与 STL 算法结合,在容器中处理动态参数。

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>void printIfGreater(int value, int threshold) 
{if (value > threshold) {std::cout << value << " ";}
}int main() 
{std::vector<int> numbers = {1, 3, 5, 7, 9, 11};// 绑定动态阈值auto bindPrintIfGreater = std::bind(printIfGreater, std::placeholders::_1, 5);std::for_each(numbers.begin(), numbers.end(), bindPrintIfGreater);// 输出: 7 9 11return 0;
}

占位符传递到嵌套函数

占位符可以在多层绑定中传递,适用于复杂嵌套调用场景。

#include <iostream>
#include <functional>void outerFunction(int x, std::function<void(int)> innerFunc) 
{std::cout << "Outer: " << x << std::endl;innerFunc(x + 1);
}void innerFunction(int y) 
{std::cout << "Inner: " << y << std::endl;
}int main() 
{// 绑定 outerFunction 的第一参数为动态传递,第二参数绑定 innerFunctionauto bindOuter = std::bind(outerFunction, std::placeholders::_1, std::bind(innerFunction, std::placeholders::_1));bindOuter(10); // 输出:// Outer: 10// Inner: 11return 0;
}

混合占位符与默认值

结合固定值和动态参数。

#include <iostream>
#include <functional>void greet(const std::string& greeting, const std::string& name, int repeat) 
{for (int i = 0; i < repeat; ++i) {std::cout << greeting << ", " << name << "!" << std::endl;}
}int main() 
{// 固定 greeting 为 "Hello",repeat 为 2,动态传递 nameauto bindGreet = std::bind(greet, "Hello", std::placeholders::_1, 2);bindGreet("Alice"); // 输出:// Hello, Alice!// Hello, Alice!bindGreet("Bob");   // 输出:// Hello, Bob!// Hello, Bob!return 0;
}

复杂占位符组合

结合静态绑定、动态参数和参数顺序调整,展示复杂调用逻辑。

#include <iostream>
#include <functional>void processValues(int x, int y, int z) 
{std::cout << "Processed: " << (x + y - z) << std::endl;
}int main() 
{// 固定 x 为 10,z 为动态传递,y 和 z 的顺序调整auto bindProcess = std::bind(processValues, 10, std::placeholders::_2, std::placeholders::_1);bindProcess(5, 20); // 实际调用: processValues(10, 20, 5)// 输出: Processed: 25return 0;
}

std::bind的原理

std::bind 的设计思路

std::bind 的设计基于 函数对象封装 和 参数转发 的思想。 std::bind 会将目标函数及其参数封装为一个可调用对象(一般是一个类), 该可调用对象重载了 operator(),从而能够模拟函数调用;对于绑定的参数,std::bind 会存储其值,对于动态传递的参数,占位符(如 std::placeholders::_1、std::placeholders::_2)会在调用时将实际参数映射到正确的位置;std::bind 是高度模板化的,其实现依赖于 完美转发 和 类型擦除,从而能够适配不同类型的函数及参数。

简化实现示例

#include <tuple>
#include <utility>
#include <iostream>// 占位符实现
template <int Index>
struct Placeholder
{template <typename... CallArgs>auto operator()(CallArgs&&... callArgs) const{return std::get<Index>(std::forward_as_tuple(callArgs...));}
};// 定义全局占位符
constexpr Placeholder<0> _1{};
constexpr Placeholder<1> _2{};// 简化版 Bind 实现
template <typename Func, typename... BoundArgs>
class Bind
{
public:Bind(Func f, BoundArgs... boundArgs): m_func(std::move(f)), m_boundArgs(std::make_tuple(std::forward<BoundArgs>(boundArgs)...)){}template <typename... CallArgs>auto operator()(CallArgs&&... callArgs){return invoke(std::index_sequence_for<BoundArgs...>{}, std::forward<CallArgs>(callArgs)...);}private:Func m_func;                          // 存储目标函数std::tuple<BoundArgs...> m_boundArgs; // 存储绑定的参数// 调用目标函数template <std::size_t... Indexes, typename... CallArgs>auto invoke(std::index_sequence<Indexes...>, CallArgs&&... callArgs){return m_func(resolve(std::get<Indexes>(m_boundArgs), callArgs...)...);}// 如果参数是值,则直接返回template <typename Arg, typename... CallArgs>static auto resolve(Arg&& arg, CallArgs&&...){return std::forward<Arg>(arg);}// 如果参数是 _1,占位符对应第一个动态传入的参数template <typename... CallArgs>static auto resolve(const Placeholder<0>&, CallArgs&&... callArgs){return std::get<0>(std::forward_as_tuple(callArgs...));}// 如果参数是 _2,占位符对应第二个动态传入的参数template <typename... CallArgs>static auto resolve(const Placeholder<1>&, CallArgs&&... callArgs){return std::get<1>(std::forward_as_tuple(callArgs...));}
};// 辅助函数
template <typename Func, typename... Args>
auto bind(Func&& func, Args&&... args) 
{return Bind<Func, Args...>(std::forward<Func>(func), std::forward<Args>(args)...);
}// 测试普通函数
int add(int a, int b)
{return a + b;
}int main()
{// 绑定 add 函数,第二个参数固定为 10auto boundAdd = bind(add, _1, 10);std::cout << "Result: " << boundAdd(5) << std::endl; // 输出: Result: 15// 绑定 add 函数,两个参数动态传入auto dynamicAdd = bind(add, _2, _1);std::cout << "Result: " << dynamicAdd(10, 5) << std::endl; // 输出: Result: 15return 0;
}

Bind的陷阱

当使用std::bind与std::shared_ptr联合创建绑定对象时,若std::shared_ptr实例作为绑定参数直接传递,会增加其引用计数。若此绑定函数被存储在生命周期较长的对象中(如事件回调或任务队列),可能导致循环引用,进而无法释放相关内存,触发内存泄漏。

示例:异步任务与回调处理

#include <iostream>
#include <functional>
#include <memory>
#include <thread>
#include <chrono>class Worker 
{
public:Worker(const std::string& name) : m_name(name) {}~Worker() {std::cout << "Worker [" << m_name << "] destroyed" << std::endl;}void doWork() {std::cout << "Worker [" << m_name << "] is working..." << std::endl;}void scheduleTask(std::function<void()> task) {// 模拟异步任务执行std::thread([task]() {std::this_thread::sleep_for(std::chrono::seconds(1));task(); // 执行回调}).detach();}private:std::string m_name;
};void example() 
{std::shared_ptr<Worker> worker = std::make_shared<Worker>("TaskWorker");// 使用std::bind捕获shared_ptr,导致引用计数增加worker->scheduleTask(std::bind(&Worker::doWork, worker));// std::bind内部增加了引用计数,阻止worker正常释放std::cout << "Worker scheduled, but not released yet..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));// worker未销毁
}

输出

TimerTask created
Running task...
(未输出 "TimerTask destroyed",表明未释放资源)

我们可通过std::weak_ptr替代std::shared_ptr,动态检查对象是否仍然有效,避免循环引用。

void exampleWithWeakPtr() 
{std::shared_ptr<Worker> worker = std::make_shared<Worker>("TaskWorker");std::weak_ptr<Worker> weakWorker = worker;worker->scheduleTask([weakWorker]() {if (auto sharedWorker = weakWorker.lock()) {sharedWorker->doWork();} else {std::cout << "Worker object no longer exists." << std::endl;}});std::cout << "Worker scheduled, attempting release..." << std::endl;worker.reset(); // 提前释放workerstd::this_thread::sleep_for(std::chrono::seconds(2));// 此时worker已销毁
}

输出

Worker scheduled, attempting release...
Worker [TaskWorker] destroyed
Worker object no longer exists.

总结

std::bind 是 C++11 提供的一个强大工具,用于灵活地处理函数调用。它能够绑定普通函数、成员函数、仿函数或 Lambda 表达式的部分参数,并通过占位符 std::placeholders 动态传递其他参数,从而在参数重排序、函数适配以及嵌套调用中发挥巨大作用。此外,std::bind 可以很好地与标准库算法结合,适用于高阶函数和动态参数传递的场景。

在使用 std::bind 时,需要注意以下几点:

  • 灵活性与复杂性:std::bind 提供了极大的灵活性,但在复杂绑定和嵌套场景中可能会使代码可读性下降。对于简单任务,优先考虑使用 Lambda 表达式。
  • 性能影响:std::bind 会生成额外的中间函数对象,在性能敏感的场景下,需要注意其开销。
  • 占位符顺序:通过 std::placeholders::_n 绑定动态参数时,需明确顺序映射关系,避免参数传递错误。

随着现代 C++ 标准的演化,std::bind 的使用场景逐渐被 Lambda 表达式取代,后者提供了更直观的语法和性能优化。然而,在某些需要函数适配器的场景中,std::bind 仍然是一个值得掌握的工具。

通过对 std::bind 的原理和实现机制的解析,可以更好地理解其设计思路和应用方式,这对深入学习现代 C++ 的函数式编程范式也具有重要意义。

相关文章:

C++11: STL之bind

C11: STL之bind 引言可调用对象的绑定绑定普通函数绑定静态函数绑定类成员函数绑定仿函数绑定Lambda 占位符std::placeholders的应用嵌套绑定参数重排序结合 STL 算法占位符传递到嵌套函数混合占位符与默认值复杂占位符组合 std::bind的原理std::bind 的设计思路简化实现示例 B…...

在线音乐播放器 —— 测试报告

自动化脚本源代码&#xff1a;Java: 利用Java解题与实现部分功能及小项目的代码集合 - Gitee.com 目录 前言 一、项目简介 1.项目背景 2.应用技术 &#xff08;1&#xff09;后端开发 &#xff08;2&#xff09;前端开发 &#xff08;3&#xff09;数据库 二、项目功能…...

等保测评讲解:安全管理中心

在数字化转型的背景下&#xff0c;网络安全的重要性愈发凸显&#xff0c;而作为中国边疆大省的黑龙江&#xff0c;其网络安全建设更是不可忽视。等保测评&#xff0c;即信息安全等级保护测评&#xff0c;是确保信息系统安全的关键环节。本文将详细讲解黑龙江等保测评中的安全管…...

vue3表单输入相关修饰符使用

在 Vue 3 中&#xff0c;.lazy、.number 和 .trim 是用于 v-model 指令的修饰符&#xff0c;它们可以帮助你在双向绑定时进行特定的处理。 1. .lazy 修饰符 .lazy 修饰符表示只在 input 事件之后触发更新&#xff0c;即输入框的内容发生变化后&#xff0c;只有在用户**失去焦…...

CSS笔记(二)类名复用

这里我通过两张不同位置的卡片来实现效果 代码 <!DOCTYPE html> <html><head><style>/*设置画布*/body{/* 方便排列与对齐*/display: flex; /*画布布满整个窗口*/height: 100vh;/*水平居中*/justify-content: center;/*垂直居中*/align-items: cente…...

TCP三次握手与四次挥手(TCP重传机制,2MSL)超详细!!!计算机网络

本篇是关于3次握手和四次挥手的详细解释~ 如果对你有帮助&#xff0c;请点个免费的赞吧&#xff0c;谢谢汪。&#xff08;点个关注也可以&#xff01;&#xff09; 如果以下内容需要补充和修改&#xff0c;请大家在评论区多多交流~。 目录 1. TCP头部&#xff1a; 2. 三次握手…...

LCR 006. 两数之和 II - 输入有序数组

一.题目&#xff1a; LCR 006. 两数之和 II - 输入有序数组 - 力扣&#xff08;LeetCode&#xff09; 二.我的原始解法-暴力解法超时&#xff1a; class Solution: def twoSum(self, numbers: List[int], target: int) -> List[int]: # 暴力解法 result [] for i in rang…...

网络安全在现代企业中的重要作用

网络安全是这个数字时代最令人担忧的事情之一。对技术的依赖性越来越强&#xff0c;使其同时面临多种网络威胁。其声誉和法律后果的大幅下降可能归因于一次妥协。 这使得良好的网络安全成为所有企业的选择和必需品。本文介绍了网络安全的重要性、企业中常见的网络威胁以及公司…...

关于 EKS Bottlerocket AMI 版本与 Karpenter 配置的说明

问题1: Bottlerocket AMI 版本问题 之前,后端团队发现在使用 Bottlerocket v1.26.2 AMI 版本时,存在某些问题。经过 Bottlerocket 团队调查,此行为是罕见的 race condition 导致的结果。 我们在环境中重现了此状况,并且关注到由于 kubelet device manager 的启动时间晚于 NVI…...

Python实现人生重开模拟器

目录 人生重开模拟器介绍 代码实现 打印初始界面 设置初始属性 设置角色性别 设置角色出生点 针对每一岁&#xff0c;生成人生经历 完整代码 人生重开模拟器介绍 人生重开模拟器 是之前比较火的一个小游戏&#xff0c;我们这里使用 Python 实现一个简化版的 人生重开模…...

java——Spring Boot的配置加载顺序和优先级

Spring Boot的配置加载顺序和优先级是确定应用程序如何读取和应用配置的关键。以下是对Spring Boot配置加载顺序和优先级的详细解释&#xff1a; 一、配置加载顺序 命令行参数&#xff1a; Spring Boot会首先加载命令行中指定的参数。这些参数可以通过在命令行中使用--keyval…...

【21-30期】Java技术深度剖析:从分库分表到微服务的核心问题解析

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Java &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 文章题目&#xff1a;Java技术深度剖析&#xff1a;从分库分表到微服务的核心问题解析 摘要&#xff1a; 本…...

CSS:怎么把网站都变成灰色

当大家看到全站的内容都变成了灰色&#xff0c;包括按钮、图片等等。这时候我们可能会好奇这是怎么做到的呢&#xff1f; 有人会以为所有的内容都统一换了一个 CSS 样式&#xff0c;图片也全换成灰色的了&#xff0c;按钮等样式也统一换成了灰色样式。但你想想这个成本也太高了…...

开发一个基于MACOS M1/2芯片的Android 12的模拟器

产品需求&#xff1a;MuMu模拟器Pro_率先适配Apple M系列芯片的安卓模拟器 苹果M芯片专属&#xff1a;产品专为苹果M系列芯片设计&#xff0c;意味着它需要能够充分利用M系列芯片的性能优势。 安卓模拟器&#xff1a;产品是一个安卓模拟器&#xff0c;允许用户在Mac设备上运行…...

Flink 中 JDBC Connector 使用详解

1. 背景 在实时计算或离线任务中&#xff0c;往往需要与关系型数据库交互&#xff0c;例如 MySQL、PostgreSQL 等。Apache Flink 提供了 JDBC Connector&#xff0c;可以方便地将流式数据写入或读取数据库。 本文将介绍 Flink JDBC Connector 的基础用法、配置方法以及注意事…...

【Linux打怪升级记 | 报错02】-bash: 警告:setlocale: LC_TIME: 无法改变区域选项 (zh_CN.UTF-8)

&#x1f5fa;️博客地图 &#x1f4cd;1、报错发现 &#x1f4cd;2、原因分析 &#x1f4cd;3、解决办法 &#x1f4cd;4、测试结果 1、报错发现 装好了CentOS操作系统&#xff0c;使用ssh远程登陆CentOS&#xff0c;出现如下告警信息&#xff1a; bash: 警告:setlocale…...

未来已来?AI技术革新改变我们的生活

在21世纪的今天&#xff0c;人工智能&#xff08;AI&#xff09;不再是一个遥远的概念&#xff0c;而是逐渐渗透到我们生活的方方面面。从智能家居到自动驾驶汽车&#xff0c;从个性化推荐系统到医疗诊断辅助&#xff0c;AI技术正在以惊人的速度发展&#xff0c;并深刻地影响着…...

【Linux】进程的生命之旅——诞生、消逝与守候(fork/exit/wait)

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出&#xff0c;万山无阻 目录 &#x1f4d6;一、进程创建 1.fork函数 &#x1f4da;高层封装特性 &#x1f4da;fork返回值 2.写时拷…...

使用vcpkg自动链接tinyxml2时莫名链接其他库(例如boost)

使用vcpkg自动链接tinyxml2时莫名链接其他库&#xff08;例如boost&#xff09; vcpkg的自动链接功能非常方便&#xff0c;但在某些情况下会出现过度链接的问题。 链接错误症状 以tinyxml2为例&#xff0c;程序中调用tinyxml2的函数后&#xff0c;若vcpkg中同时存在opencv和…...

【去毛刺】OpenCV图像处理基础:腐蚀与膨胀操作入门

在数字图像处理中&#xff0c;形态学操作是一种常用的技术&#xff0c;用于提取图像中的特定形状或特征。其中&#xff0c;腐蚀&#xff08;Erosion&#xff09;和膨胀&#xff08;Dilation&#xff09;是两种基本的形态学运算。本文将通过一个简单的例子来演示如何使用Python中…...

道可云人工智能元宇宙每日资讯|第三届京西地区发展论坛成功召开

道可云元宇宙每日简报&#xff08;2024年11月27日&#xff09;讯&#xff0c;今日元宇宙新鲜事有&#xff1a; 工信部等十二部门印发《5G规模化应用“扬帆”行动升级方案》 11月25日&#xff0c;工业和信息化部等十二部门印发《5G规模化应用“扬帆”行动升级方案》。《方案》…...

若依框架部署在网站一个子目录下(/admin)问题(

部署在子目录下首先修改vue.config.js文件&#xff1a; 问题一&#xff1a;登陆之后跳转到了404页面问题&#xff0c;解决办法如下&#xff1a; src/router/index.js 把404页面直接变成了首页&#xff08;大佬有啥优雅的解决办法求告知&#xff09; 问题二&#xff1a;退出登录…...

【ue5】UE5运行时下载视频/UE5 runtime download video(MP4)

插件还是老朋友。 节点的content type要打对。 &#xff08;参照表&#xff1a;MIME 类型&#xff08;MIME Type&#xff09;完整对照表 - 免费在线工具&#xff09; 结果展示&#xff1a;...

对比C++,Rust在内存安全上做的努力

简介 近年来&#xff0c;越来越多的组织表示&#xff0c;如果新项目在技术选型时需要使用系统级开发语言&#xff0c;那么不要选择使用C/C这种内存不安全的系统语言&#xff0c;推荐使用内存安全的Rust作为替代。 谷歌也声称&#xff0c;Android 的安全漏洞&#xff0c;从 20…...

如何利用 Qt 的模块化架构组织大型项目

目录 1. 大型项目的架构设计 1.1 分层架构 1.2 事件驱动与异步架构 2. 模块划分与职责分离 2.1 功能模块划分 2.2 模块之间的依赖管理 3. 跨平台开发与模块复用 在大型软件项目中&#xff0c;随着代码量的增加和功能的扩展&#xff0c;项目的复杂度会显著提升。没有良好…...

探索Python词云库WordCloud的奥秘

文章目录 探索Python词云库WordCloud的奥秘1. 背景介绍&#xff1a;为何选择WordCloud&#xff1f;2. WordCloud库简介3. 安装WordCloud库4. 简单函数使用方法5. 应用场景示例6. 常见Bug及解决方案7. 总结 探索Python词云库WordCloud的奥秘 1. 背景介绍&#xff1a;为何选择Wo…...

MySQL根据idb文件恢复数据

首先得有对应表的idb文件以及建表语句 1.首先在新数据库建表 CREATE TABLE sys_menu (id bigint(20) NOT NULL,parent_id bigint(20) NULL DEFAULT NULL,name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,type int(11) NULL DEFAULT …...

hadoop-mapreduce词频统计

一、Map Reduce主要阶段 二、词频统计示例 0.MapReduce 词频统计(Word Count)示例图 1. Input 阶段&#xff08;输入阶段&#xff09; 输入数据是一段文本&#xff0c;如下&#xff1a; Hadoop is a big data framework. Hadoop can store vast data. Hadoop processes big …...

精心修炼Java并发编程(JUC)-volatile与synchronized关键字

volatile volatile 是 JVM 提供的 最轻量级的同步机制&#xff0c;中文意思是不稳定的&#xff0c;易变的&#xff0c;用 volatile 修饰变量是为了保证变量在多线程中的可见性&#xff0c;它表达的含义是&#xff1a;告诉编译器&#xff0c;对这个变量的读写&#xff0c;需要基…...

【ROS2】ROS2 与 ROS1 编码方式对比(Python实现)

目录 一、初始化和关闭节点二、发布者三、订阅者四、服务端五、客户端六、参数管理七、日志记录八、生命周期管理 ROS2 在 Python 编程中引入了一些新的概念和 API&#xff0c;这些变化使得代码更加模块化和易于维护。特别是 rclpy 库提供了更丰富的功能和更好的错误处理机制&a…...

大连市建委培训官方网站/什么是推广

正整数可以表示为若干正整数的累加和。如&#xff0c;对于正整数n6&#xff0c;可以分划为&#xff1a; 51 42 411 33 321 3111 222 2211 21111 111111现在的问题是&#xff0c;对于给定的正整数n,计算出所有划分情况。下面的代码实现了这个功能。仔细分析&#xff0c;填写划线…...

吧网站做软件的软件下载/网推app怎么推广

安装证书文件说明&#xff1a;1. 证书文件214032361520874.pem&#xff0c;包含两段内容&#xff0c;请不要删除任何一段内容。2. 如果是证书系统创建的CSR&#xff0c;还包含&#xff1a;证书私钥文件214032361520874.key。( 1 ) 在Nginx的安装目录下创建cert目录&#xff0c;…...

python做软件的网站/流量点击推广平台

车架号车型发动机和变速箱型号行驶里程4JGDF7DE7DA120825GL550276928和72290967345故障现象(陈述)&#xff1a;此车在车库放了3个月&#xff0c;去启动无反应&#xff0c;接到客户救援电话最后直接拿上一个原厂电瓶给客户换上&#xff0c;换上之后车能正常启动&#xff0c;但是…...

如何做视频购物网站/海口网站关键词优化

NoSQL Manager的安装和使用 https://www.cnblogs.com/TurboWay/p/8213656.html...

怎样做网站文件验证/网络营销郑州优化推广公司

网友 OOXX 在找好用的 webmail&#xff0c;老苏觉得 Cypht 还不错 什么是 Cypht &#xff1f; Cypht 是一个简单、轻量级和现代的 Webmail 客户端&#xff0c;它将多个帐户聚合到一个界面中。除了电子邮件帐户&#xff0c;它还支持 Atom/RSS 源。 安装 建数据库 数据库直接用…...

做网站用php哪些知识点/自己建网站怎么建

声明&#xff1a; ● 本专栏是自己在学习慕课网Liuyubobobo老师的《算法与数据结构体系课》 时&#xff0c;自己做的笔记&#xff1b; ● 主要目的是供自己学习、总结、回顾之用&#xff0c;其中很多内容书写记录的时候包含了很多个人语言&#xff1b; ● 读者如果想更好的理解…...