项目前置知识——不定参以及设计模式
1.C语言不定参宏函数
c语言中,printf就是一个不定参函数,在使用不定参宏函数时,我们使用__VA_ARGS__来解析不定参:
#include <iostream>
#include <cstdarg>#define LOG(fmt/*格式*/, .../*用...表示不定参*/) printf("[%s:%d]"fmt, __FILE__, __LINE__, __VA_ARGS__)int main()
{LOG("%s", "test for Indefinite parameter");LOG("%s-%d", "aaaaaa", 1233456);return 0;
}
运行结果:
[test.cc:9]test for Indefinite parameter
[test.cc:10]aaaaaa-1233456
但是当我们只传入一个格式字符串,而没有后面的不定参,此时该宏就会出错
LOG("only fmt");
这是因为只传入一个fmt,此时LOG会被替换成为 -> printf("[%s:%d]" "only fmt", "test.cc", "11", );
可以看到,多了一个逗号,此时printf解析时,就会出错。所以,为了避免这个问题,我们需要在使用__VA_ARGS__时前面加上##,##的作用就是在不定参为空时,删除逗号。
2.C语言不定参函数
同样,在函数中,用...表示不定参。在函数中,我们使用va_list、va_start、va_arg、va_end来解析不定参。
#include <iostream>
#include <cstdio>
#include <cstdarg>void Print(int count, ...)
{va_list ap;va_start(ap, count);for(int i=0; i<count; i++) {int num = va_arg(ap, int);printf("arg[%d]:%d\n", i+1, num);}va_end(ap);
}int main()
{Print(1, 1);std::cout << std::endl;Print(2, 1, 2);std::cout << std::endl;Print(3, 1, 2, 3);return 0;
}
- va_list:特殊数据结构,相当于一个指针,用来管理所有的不定参列表;
- va_start(ap,param):用于初始化va_list列表,ap表示va_list数据结构,param表示不定参前的第一个固定参数。(在调用函数时,要创建函数栈帧,同时会进行参数压栈,va_start的作用就是获取固定参数的压栈位置,让ap指向该固定位置的下一个位置,即不定参的第一个位置)。
- va_arg(ap, type):用于获取下一个可变参数的值。ap表示不定参数列表,type表示下一个不定参的数据类型。同时,用va_arg之后,ap会自动指向下一个不定参。所以,va_arg在使用前,必须得知不定参的类型。
- va_end(ap):可变参数列表使用完之后,用该函数进行清理,释放资源。
使用vasprintf结合不定参列表实现myPrintf
vasprintf:用于将可变参数按照格式化字符串生成动态分配的字符串
#include <iostream> #include <cstdio> #include <cstdarg>void myPrintf(const char *fmt, ...) {va_list ap;va_start(ap, fmt);char *str;int n = vasprintf(&str, fmt, ap);if(n == -1) {std::cerr << "vasprintf error" << std::endl;va_end(ap);return;}va_end(ap);printf("%s", str);free(str); }int main() {myPrintf("%d\n", 123456);myPrintf("%s\n", "hahahahaha");myPrintf("[%s:%d]-%s\n", __FILE__, __LINE__, "test my printf");return 0; }
3.C++不定参函数
c++不定参函数,在编译时进行递归式包扩展,每一次会将参数包的一个参数提到t中,参数包少一个参数,当参数包为空时,此时就会调用无参Print,此时参数包解析完毕
在解析过程中,使用forward完美转发,确保参数包的参数在解析过程中,属性不变(左值还是左值,右值还是右值)。
#include <iostream>
#include <cstdio>
#include <cstdarg>void Print()
{std::cout << std::endl;
}template <typename T, typename ...Args>
void Print(const T& t, Args &&...args)
{std::cout << t << " ";Print(std::forward<Args>(args)...);
}int main()
{Print("123"); Print("123", 1209); Print("123", "456", "test for c++ args"); return 0;
}
4.设计模式
4.1设计模式的六大原则
0x1.单一职责原则(SRP:Single Responsibility Principle)
- 定义:一个类应该只有一个引起它变化的原因,也就是说一个类只负责干一件事。避免类和类之间的功能耦合
- 应用场景:将用户管理(注册、登录)与权限验证分离。文件操作类拆分为读取和写入两个独立类。
0x2. 开闭原则(OCP:Open/Closed Principle)
- 定义:软件实体应当对扩展开放,对修改关闭。即软件中的类、模块、函数等应该可以在不修改原有代码的基础上进行功能扩展。即通过抽象和多态实现扩展,而非修改原有代码。
- 应用场景:使用接口 / 抽象类定义规范,通过子类扩展功能。
0x3. 里氏替换原则(LSP:Liskov Substitution Principle)
- 定义:子类可以替换其父类且不影响程序的正确性。本质上就是多态的应用,子类重写父类的虚方法,可以用父类指针指向子类对象。
- 应用场景: 在使用继承机制构建类层次结构时,需要遵循里氏替换原则。比如在一个图形编辑软件中,有一个图形基类,用于定义图形的基本属性和操作,如移动、缩放。圆形、矩形等具体图形类继承自这个基类。当需要对图形进行统一操作(如批量移动图形)时,就可以利用基类的引用指向不同子类的实例来实现,而不需要关心具体是哪种图形。
0x4.依赖倒置原则(DIP:Dependency Inversion Principle)
- 定义:高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。什么意思呢?就是说,类与类之间的交互,都通过它们的抽象基类来交互,而不通过具体的某一个类。这样我们就可以在高层模块中进行底层模块的替换。
- 应用场景:比如我们正在开发游戏,有两种武器(剑,弓),两种角色(剑士,弓箭手)。而我们在实现角色类时,不要将角色与武器绑死,而是在角色内部使用基类指向武器,我们根据传入武器的类型,来判断到底是什么角色。
0x5.接口隔离原则(ISP:Interface Segregation Principle)
- 定义: 客户端不应该依赖它不需要的接口。实现思路:将本应该设计到一个基类中的虚函数接口,重新定义为一个一个的子项(类,该类中只有一个虚函数成员接口),再想实现具体类时,可以根据具体需要的功能,继承不同的子项类。
- 应用场景:有一个打印机接口,其中包含了打印、复印、扫描等多个方法。但有些打印机(如小型便携式打印机)可能只支持打印功能。按照接口隔离原则,应该将这些功能分成不同的接口,如打印接口、复印接口、扫描接口,这样小型打印机就可以只实现打印接口,避免了实现不需要的接口方法。
0x6.迪米特法则(LoD:Law of Demeter,最少知识原则)
- 定义:一个对象应该对其他对象有最少的了解。
- 应用场景:在一个学生成绩管理系统中,学生类和成绩类是直接相关的,成绩类和课程类也是直接相关的。但是学生类不应该直接操作课程类,而应该通过成绩类来进行间接操作。这样可以降低对象之间的耦合度。
5.单例模式
单例模式,确保一个类只能实例化出一个实例,并提供一个全局访问点来获取该实例。
而创建单例的方式有两种:饿汉模式和懒汉模式。
5.1饿汉模式创建单例
在程序启动时就会创建出一个实例。但因为不管我们是否使用该实例,都会在程序启动时创建,所以饿汉模式可能会影响程序的启动速度。
所以饿汉模式一般适用于实例创建开销小,或需要在程序启动时立即初始化的情况。
class SinglEton
{
public:static SinglEton& getInstance() { return _eton; }private:// 构造函数私有化,并且避免拷贝对象,所以删除拷贝构造和赋值SinglEton(){}SinglEton(const SinglEton& se) = delete;SinglEton operator=(const SinglEton& se) = delete;
private:static SinglEton _eton;
};// 立即实例化单例对象
SinglEton SinglEton::_eton;
饿汉模式创建单例是线程安全的,多线程进入getInstance获取的都是同一个单例,因为单例早已经创建好了。
2.懒汉模式创建单例
在第一次使用单例时,才开始创建实例。懒汉模式其实是一种延迟初始化的思想。
适用于单例对象构造特别耗时或者耗费济 源(加载插件、加载⽹络资源等)的情况。
2.1double-check懒汉单例
class LazySingleton
{
public:static LazySingleton* getInstance(){if(!_instance) {std::lock_guard<std::mutex> lock(_mutex);if(!_instance) {_instance = new LazySingleton();}}return _instance;}
private:LazySingleton(){}LazySingleton(const LazySingleton &lse) = delete;LazySingleton operator=(const LazySingleton &lse) = delete;
private:static LazySingleton* _instance;static std::mutex _mutex;
};// 静态成员初始化
LazySingleton* LazySingleton::_instance = nullptr;
std::mutex LazySingleton::_mutex;
第一次检查,如果不为空,直接返回,提高程序性能(实例创建好后,以后的线程就不再需要加锁在访问了)
第二次检查,此时已加锁,再次判断是否为空(因为在加锁期间,可能已经有线程创建了单例)。
2.2 Meyers 单例(C++11 及以后)
class MeyersSingleton {
private:MeyersSingleton() = default;~MeyersSingleton() = default;MeyersSingleton(const MeyersSingleton&) = delete;MeyersSingleton& operator=(const MeyersSingleton&) = delete;public:static MeyersSingleton& getInstance() {static MeyersSingleton instance; // 线程安全的局部静态变量return instance;}
};
之所以能够这么创建单例,是因为c++11以后,局部静态变量的初始化是线程安全的,编译器会保证即使在多线程环境下,也只会初始化一次。每次调用 getInstance()
方法时,都会返回同一个 instance
对象的引用。
6.工厂模式
工厂模式是一种创建型设计模式,它将对象的创建和使用分离,通过工厂类来负责创建对象。这种模式可以提高代码的可维护性和可扩展性。
6.1简单工厂模式
简单工厂模式是工厂模式的基础形式,它定义一个工厂类来创建产品对象。根据指定的类型,创建出指定类型的产品。适用于产品种类较少且不会频繁变化的场景。
但是简单工厂模式不满足6大原则中的开闭原则,当有了新产品,我们需要在原有代码上进行修改。
#include <iostream>
#include <memory>// 抽象产品类
class Product {
public:virtual void operation() const = 0;virtual ~Product() = default;
};// 具体产品类A
class ConcreteProductA : public Product {
public:void operation() const override {std::cout << "ConcreteProductA operation" << std::endl;}
};// 具体产品类B
class ConcreteProductB : public Product {
public:void operation() const override {std::cout << "ConcreteProductB operation" << std::endl;}
};// 简单工厂类
class SimpleFactory {
public:static std::unique_ptr<Product> createProduct(char type) {switch (type) {case 'A':return std::make_unique<ConcreteProductA>();case 'B':return std::make_unique<ConcreteProductB>();default:throw std::invalid_argument("Invalid product type");}}
};
6.2工厂方法模式
由抽象工厂类,派生出具体工厂类,每一个工厂负责生产一个专门的产品。便于扩展新的产品种类,符合开闭原则。
#include <iostream>
#include <memory>// 抽象产品类
class Product {
public:virtual void operation() const = 0;virtual ~Product() = default;
};// 具体产品类
class ConcreteProductA : public Product {
public:void operation() const override {std::cout << "ConcreteProductA operation" << std::endl;}
};class ConcreteProductB : public Product {
public:void operation() const override {std::cout << "ConcreteProductB operation" << std::endl;}
};// 抽象工厂类
class Factory {
public:virtual std::unique_ptr<Product> createProduct() const = 0;virtual ~Factory() = default;
};// 具体工厂类
class ConcreteFactoryA : public Factory {
public:std::unique_ptr<Product> createProduct() const override {return std::make_unique<ConcreteProductA>();}
};class ConcreteFactoryB : public Factory {
public:std::unique_ptr<Product> createProduct() const override {return std::make_unique<ConcreteProductB>();}
};
6.3抽象工厂模式
在产品类型较多的情况下,由抽象工厂类派生出具体的工厂类,这些工厂类都有相同的功能,只不过产生的是不同商家的产品。适用于产品组合较多且需要一起使用的情况。
下面以一个开发游戏的例子来说明:
// 武器抽象类
class Weapon {
public:virtual void attack() const = 0;virtual ~Weapon() = default;
};// 防具抽象类
class Armor {
public:virtual void defend() const = 0;virtual ~Armor() = default;
};
// 现代武器
class ModernGun : public Weapon {
public:void attack() const override {std::cout << "使用现代枪械射击!" << std::endl;}
};// 现代防具
class ModernVest : public Armor {
public:void defend() const override {std::cout << "使用防弹衣防御!" << std::endl;}
};// 中世纪武器
class MedievalSword : public Weapon {
public:void attack() const override {std::cout << "使用中世纪长剑挥砍!" << std::endl;}
};// 中世纪防具
class MedievalPlate : public Armor {
public:void defend() const override {std::cout << "使用全身板甲防御!" << std::endl;}
};// 未来武器
class FutureLaser : public Weapon {
public:void attack() const override {std::cout << "使用激光武器射击!" << std::endl;}
};// 未来防具
class FutureShield : public Armor {
public:void defend() const override {std::cout << "使用能量护盾防御!" << std::endl;}
};
// 装备工厂抽象类
class EquipmentFactory {
public:virtual std::unique_ptr<Weapon> createWeapon() const = 0;virtual std::unique_ptr<Armor> createArmor() const = 0;virtual ~EquipmentFactory() = default;
};
// 现代装备工厂
class ModernEquipmentFactory : public EquipmentFactory {
public:std::unique_ptr<Weapon> createWeapon() const override {return std::make_unique<ModernGun>();}std::unique_ptr<Armor> createArmor() const override {return std::make_unique<ModernVest>();}
};// 中世纪装备工厂
class MedievalEquipmentFactory : public EquipmentFactory {
public:std::unique_ptr<Weapon> createWeapon() const override {return std::make_unique<MedievalSword>();}std::unique_ptr<Armor> createArmor() const override {return std::make_unique<MedievalPlate>();}
};// 未来装备工厂
class FutureEquipmentFactory : public EquipmentFactory {
public:std::unique_ptr<Weapon> createWeapon() const override {return std::make_unique<FutureLaser>();}std::unique_ptr<Armor> createArmor() const override {return std::make_unique<FutureShield>();}
};
7.建造者模式
建造者模式(Builder Pattern)是一种创建型设计模式,它允许我们分步骤构建复杂对象,并且允许相同的构建过程创建不同的表示。它将构建过程与其表示分离,使相同的构建过程可以创建不同的表示。简单来说,就是创建一个对象需要很多部件,建造者模式允许我们先创建出这些部件,再有这些部件创造出一个我们所需要的对象
建者造模式的结构
-
产品(Product):要创建的复杂对象。
-
抽象建造者(Builder):声明创建产品各部件的抽象接口。
-
具体建造者(Concrete Builder):实现抽象建造者接口,构建并装配产品部件。
-
指挥者(Director):使用具体建造者来构建产品,它不依赖于产品具体类。
#include <iostream>
#include <memory>
#include <vector>
#include <string>// 产品类:汽车
class Car {
private:std::string engine;std::string chassis;std::vector<std::string> wheels;std::string body;std::string interior;public:void setEngine(const std::string& eng) { engine = eng; }void setChassis(const std::string& chs) { chassis = chs; }void addWheel(const std::string& wl) { wheels.push_back(wl); }void setBody(const std::string& bd) { body = bd; }void setInterior(const std::string& intr) { interior = intr; }void display() const {std::cout << "Car Details:\n";std::cout << "Engine: " << engine << "\n";std::cout << "Chassis: " << chassis << "\n";std::cout << "Wheels: ";for (const auto& wheel : wheels) {std::cout << wheel << " ";}std::cout << "\nBody: " << body << "\n";std::cout << "Interior: " << interior << "\n";}
};// 抽象建造者
class CarBuilder {
public:virtual void buildEngine() = 0;virtual void buildChassis() = 0;virtual void buildWheels() = 0;virtual void buildBody() = 0;virtual void buildInterior() = 0;virtual Car getResult() = 0;
};// 具体建造者:SUV建造者
class SUVBuilder : public CarBuilder {
private:Car car;public:void buildEngine() override {car.setEngine("Powerful V6 Engine");}void buildChassis() override {car.setChassis("Heavy-Duty Chassis");}void buildWheels() override {car.addWheel("All-Terrain Wheel");car.addWheel("All-Terrain Wheel");car.addWheel("All-Terrain Wheel");car.addWheel("All-Terrain Wheel");}void buildBody() override {car.setBody("Robust SUV Body");}void buildInterior() override {car.setInterior("Luxurious SUV Interior");}Car getResult() override {return car;}
};// 具体建造者:轿车建造者
class SedanBuilder : public CarBuilder {
private:Car car;public:void buildEngine() override {car.setEngine("Efficient I4 Engine");}void buildChassis() override {car.setChassis("Standard Chassis");}void buildWheels() override {car.addWheel("Regular Wheel");car.addWheel("Regular Wheel");car.addWheel("Regular Wheel");car.addWheel("Regular Wheel");}void buildBody() override {car.setBody("Sleek Sedan Body");}void buildInterior() override {car.setInterior("Comfortable Sedan Interior");}Car getResult() override {return car;}
};// 指挥者
class Director {
public:void constructCar(CarBuilder& builder) {builder.buildEngine();builder.buildChassis();builder.buildWheels();builder.buildBody();builder.buildInterior();}
};
在建造者模式中,指挥者类是用来组装所有部件来构建对象的类,因为有些对象的创建是有顺序的。
相关文章:

项目前置知识——不定参以及设计模式
1.C语言不定参宏函数 c语言中,printf就是一个不定参函数,在使用不定参宏函数时,我们使用__VA_ARGS__来解析不定参: #include <iostream> #include <cstdarg>#define LOG(fmt/*格式*/, .../*用...表示不定参*/) prin…...

04powerbi-度量值-筛选引擎CALCULATE()
1、calculate calculate 的参数分两部分,分别是计算器和筛选器 2、多条件calculater与表筛选 多条件有不列的多条件 相同列的多条件 3、calculatertable (表,筛选条件)表筛选 与calculate用法一样,可以用创建表&…...
JavaScript排序算法详解:从基础到高级
排序是编程中最基本也是最重要的操作之一。JavaScript作为一门广泛应用于Web开发的语言,提供了内置的排序方法,但了解各种排序算法的原理和实现对于开发者来说仍然至关重要。本文将深入探讨JavaScript中常见的排序算法,帮助您理解它们的原理、…...

chromedriver 下载失败
问题描述 chromedriver 2.46.0 下载失败 淘宝https://registry.npmmirror.com/chromedriver/2.46/chromedriver_win32.zip无法下载 解决方法 找到可下载源 https://cdn.npmmirror.com/binaries/chromedriver/2.46/chromedriver_win32.zip ,先将其下载到本地目录(D…...

Weather app using Django - Python
我们的任务是使用 Django 创建一个 Weather 应用程序,让用户可以输入城市名称并查看当前天气详细信息,例如温度、湿度和压力。我们将通过设置一个 Django 项目,创建一个视图来从 OpenWeatherMap API 获取数据,并设计一个简单的模板…...

机器视觉2,硬件选型
机器视觉1,学习了硬件的基本知识和选型,现在另外的教材巩固知识 选相机 工业相机选型的保姆级教程_哔哩哔哩_bilibili 1.先看精度多少mm,被检测物体长宽多少mm》分辨率, 选出合理范围内的相机 2.靶面尺寸,得出分…...
自定义序列生成器之单体架构实现
主键 ID VS 业务 ID 在数据库设计中,除了主键 ID,一般还需要一个具有唯一索引的业务 ID。二者承担的职责不一样,它们共同满足了我们对于 技术实现 和 业务需求 的双重目标 1. 职责分离原则 主键 ID 业务唯一标识 ID 作用 保证数据库层面…...

电阻电容的选型
一、电阻选型 1.1安装方式 贴片电阻体积小,适用于SMT生产;功率小;易拆解插件电阻体积大;功率大;不易脱落 1.2阻值 电阻的阻值是离散的,其标称阻值根据精度分为E6、E12、E24、E48、E96、E192六大系列&am…...

12.springCloud AlibabaSentinel实现熔断与限流
目录 一、Sentinel简介 1.官网 2.Sentinel 是什么 3.Sentinel 的历史 4.Sentinel 基本概念 资源 规则 5.Sentinel 功能和设计理念 (1).流量控制 什么是流量控制 流量控制设计理念 (2).断降级 什么是熔断降级 熔断降级设计理念 (3).系统自适应保护 6.主要工作机制…...
Cookie 和 Session:Web 身份验证的核心机制
文章目录 一、Cookie:客户端存储的小数据块**核心特性****典型应用场景**二、Session:服务器端的会话存储**核心特性****典型应用场景**三、Cookie vs Session:核心区别对比四、最佳实践与扩展 一、Cookie:客户端存储的小数据块 …...

vSOME/IP与ETAS DSOME/IP通信的问题解决方案
✅ 一、服务版本不匹配导致 Handover 问题 —— 需要更新 VSOMEIP 代码逻辑 📌 问题描述: 在 SOME/IP 通信中,发布者(offer)与订阅者(subscribe)之间存在服务版本不一致的问题,导致 Handover(切换)失败。 ✅ 解决方案: 需要在 offer_service 和 subscribe 接口中…...
修改vscode切换上一个/下一个标签页快捷键
装了vim后一直没找到切tab页的快捷键 Code>Preferences>Keyboard Shortcuts on macOS 搜索这2个选项 我设置成了commandh 向前切换,commandl向后切换,贴合vim的方向设置 workbench.action.previousEditor commandh workbench.action.nextEdit…...
三大中文wordpress原创主题汉主题
汉主题 汉主题是一款极具特色的 WordPress 主题,由国内专业团队精心打造,专为中文用户设计。其设计灵感源自博大精深的汉文化,将传统文化元素与现代网页设计理念巧妙融合,呈现出独特而典雅的风格。无论是用于个人博客展示文学创作…...

软考-系统架构设计师-第十五章 信息系统架构设计理论与实践
信息系统架构设计理论与实践 15.2 信息系统架构风格和分类15.3 信息系统常用的架构模型15.4 企业信息系统总体框架15.5 信息系统架构设计方法 15.2 信息系统架构风格和分类 信息系统架构风格 数据流体系结构风格:批处理、管道-过滤器调用/返回体系结构风格&#x…...
Redis缓存-数据淘汰策略
数据淘汰策略就是,当redis内存满的时候,此时在向redis添加新的key,那么redis会按照某一种规则将内存中的数据删掉,这种删除数据的规则成为内存的淘汰策略。 redis支持8中淘汰策略 1.noeviction,这种是redis默认的情况…...
52. N 皇后 II【 力扣(LeetCode) 】
文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 52. N 皇后 II 一、题目描述 n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上,并且使皇后彼此之间不能相互攻击。【补充:不能互相攻击就是要求一个皇后的…...

MySQL 8 完整安装指南(Ubuntu 22.04)
MySQL 8 完整安装指南(Ubuntu 22.04) 本教程详细说明如何在 Ubuntu 22.04 上安装和配置 MySQL 8,包含安全优化及远程访问设置。 1️⃣ 添加 MySQL 官方 APT 仓库 官网仓库下载地址:MySQL APT 仓库下载页 下载仓库配置包&#…...
C++ 标准输入输出 -- <iostream>
<iostream>库是 C++ 标准库中用于输入输出操作的头文件。 <iostream> 定义了几个常用的流类和操作符,允许程序与标准输入输出设备(如键盘和屏幕)进行交互。 以下是<iostream>库的详细使用说明,包括其主要类和常见用法示例。 主要类 std::istream:用于…...
记一次sql按经纬度计算距离
具体代码: ROUND函数在mysql可以用来计算经纬度,代码如下: SELECTa.store_name_sfa as storeName,a.storeid_sfa as store_id,a.link_man_sfa as link_man,a.link_phon_sfa as link_phone,a.photo as image_url,a.district,a.street,ROUND(6…...

安卓jetpack compose学习笔记-UI基础学习
哲学知识应该用哲学的方式学习,技术知识也应该用技术的方式学习。没必要用哲学的态度来学习技术。 学完安卓技术能做事就ok了,安卓技术肯定是有哲学的,但是在初学阶段没必要讨论什么安卓哲学。 学习一们复杂技术的路径有很多,这里…...
线性回归用于分类
线性回归本身是一种用于回归问题的技术,即预测一个连续的目标变量值。然而,线性回归也可以被改造或结合其他技术来用于分类问题,尽管这不是其最直接或最常见的用途。以下是几种将线性回归应用于分类问题的方法或相关概念: 阈值划分…...
解锁电商新势能:商城系统自动 SaaS 多开功能深度解析
在电商行业加速向精细化、多元化运营转型的当下,传统的商城系统部署模式已难以满足企业快速拓展业务的需求。此时,商城系统自动 SaaS 多开功能横空出世,以智能、高效、灵活的特性,成为众多电商企业突破发展瓶颈的关键利器。这一功…...

蓝桥杯_DS18B20温度传感器---新手入门级别超级详细解析
目录 一、引言 DS18B20的原理图 单总线简介: 编辑暂存器简介: DS18B20的温度转换与读取流程 二、代码配置 maic文件 疑问 关于不同格式化输出符号的使用 为什么要rd_temperature()/16.0? onewire.h文件 这个配置为什么要先读lo…...

C++中锁与原子操作的区别及取舍策略
文章目录 锁与原子操作的基本概念锁(Lock)原子操作(Atomic Operations) 锁与原子操作的区别1. **功能**2. **性能**3. **复杂性**4. **适用场景** 锁与原子操作的取舍策略1. **简单变量操作**2. **复杂共享资源**3. **性能敏感场景…...
ESP32对接巴法云实现配网
目录 序言准备工作巴法云注册与使用Arduino准备 开发开始配网 序言 本文部分内容摘抄原创作者巴法云-做优秀的物联网平台 代码有部分修改并测试运行正常 巴法云支持免费用户通过开发对接实现各智能音箱设备语音控制智能家居设备,并有自己的App进行配网和控制&…...
《深度剖析:基于Meta的GameFormer构建自博弈AI游戏代理》
自博弈AI游戏代理,是一种具备自主学习和自我提升能力的人工智能系统。它打破了传统AI依赖预设规则和固定策略的局限,能够在游戏过程中不断与自身进行对战,通过反复博弈来积累经验、优化策略,从而实现智能水平的持续提升 。这种独特…...

C++语法系列之类型转换
前言 类型转换是经常存在的情况,类型转换分为隐式类型转化 和 显式类型转化 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败 double i 3.3; int b i; //隐式类型转化 double -> intC搞出来了四种强制类…...
Qwen3 技术报告解读一
📘 Qwen3 技术报告解读:通义千问系列新成员的技术亮点与能力分析 一、论文写了什么? 本文来自阿里通义实验室发布的 《Qwen3 Technical Report》,介绍了其最新一代大语言模型 Qwen3 的技术架构、训练方法以及在多个关键任务上的…...

详解开漏输出和推挽输出
开漏输出和推挽输出 以上是 GPIO 配置为输出时的内部示意图,我们要关注的其实就是这两个 MOS 管的开关状态,可以组合出四种状态: 两个 MOS 管都关闭时,输出处于一个浮空状态,此时他对其他点的电阻是无穷大的ÿ…...

【八股消消乐】索引失效与优化方法总结
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点ÿ…...