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

C++11特性补充

目录

lambda表达式

定义

捕捉的方式

可变模板参数

递归函数方式展开参数包

数组展开参数包

移动构造和移动赋值

包装器

绑定bind

智能指针

RAII

auto_ptr

unique_ptr

shared_ptr

循环引用

weak_ptr

补充

总结

特殊类的设计

不能被拷贝的类

只能在堆上创建类

将构造函数私有

将析构函数私有

只能在栈上创建对象

 只能创建一个对象(单例模式)

饿汉模式

懒汉模式

单例对象的释放


本文是对上一篇文章《C++11新特性》的补充,将会介绍过很多的C++11特性。

C++11新特性-CSDN博客文章浏览阅读987次,点赞30次,收藏30次。本文对C++11重要特性进行介绍,重点解析了C++中的左值引用和右值引用的区别,帮助读者快速了解C++11新特性以及这些特性的使用方法。 https://blog.csdn.net/2401_87944878/article/details/147116766

lambda表达式

定义

C++中可调用对象有三种:函数,仿函数,以及lambda表达式。

函数的类型写起来太繁琐了,所以一般都会使用仿函数来替代函数,但是对于实现简单的函数实现,使用仿函数代码长,比较笨重;因此引出了lambda表达式来解决这一问题。

lambda表达式包含三个部分:1)捕捉列表;2)函数参数;3)函数返回值类型;4)函数体。

struct Add1
{int operator()(int x, int y){return x + y;}
};
auto Add2 = [](int x, int y)->int {return x + y  ;};
Add1()(1, 1);
Add2(1, 1);

以上分别是仿函数和lambda表达式实现加法函数,可以看出lambda表达式的使用更简约。

对于lambda表达式,如果没有参数,参数部分可以省略;返回值类型也可以不写,让编译器自动推导。

auto Add3 = [](int x, int y) {return x + y; };

函数指针---在C++中人不用就不用,其类型写起来不太方便;

仿函数---是一个类,重载了operator(); 

lambda---表达本质上是一个局部匿名函数对象。

lambda表达式的函数体内可以直接调用全局变量,但是不能直接调用局部变量或局部函数。如果需要使用局部对象就要将其添加至捕捉列表中。

void test_02()
{double rate = 0.5;auto Add3 = [rate](int x, int y) {return (x + y)*rate; };}

如上图,rate就实现了捕捉,在lambda表达式中可以只用rate。

捕捉的方式

捕捉的方式有四种:

1)[var],对var进行值捕捉;

2)[&var],对var进行引用捕捉,lambda表达式中var的改变会影响其外部的var;

3)[ = ],对局部变量和函数进行全部值捕捉;

4)[ & ],对局部变量和函数进行全部引用捕捉。

当然捕捉列表也可以混合起来使用。

int a = 1, b = 2;
int c = 10;
auto Add4 = [&, c] { a++, b++;cout << c; };

以上就是混合捕捉:对所有局部变量进行引用捕捉,除了c使用值捕捉。

lambda表达式的底层实际上还是仿函数。

lambda表达式在进行值捕捉的时候,默认捕捉后的类型是const修饰的,也就是说进行值捕捉后的参数是不能进行修改的,如果想要修改需要添加mutable关键字

int a = 1, b = 2;
auto Add4 = [a, b]()mutable { a++, b++;cout << a << b; };

 使用mutable后,值捕捉的变量就就可以实现修改了。


可变模板参数

在C语言中就已经有可变参数的概念了,比如printf和scnaf的参数都属于可变参数;C++引入了模板概念,自然也有了可变模板参数概念。 

在C++11新增了可变模板参数,使得模板中参数可以不是固定的了,但是可变模板参数使用起来不太方便,此处我们进行简略介绍。

模板的参数是类型,函数的参数是对象,要将这两点分开。

template<class ... Args>
void Show(Args ... args)
{sizeof...(args);//....
}

模板中的Args指的是模板参数包,函数中的args指的是函数参数包;其中...表示其是可变参数,此处需要注意省略号的位置;通过sizeof...(args)可以打印出参数的个数。

参数包的语法不支持直接使用args[i],所以参数包是不能直接使用的,需要先展开再使用;

递归函数方式展开参数包

通过递归依次减少参数,直到参数为零,其与参数递归类似,只不过递归停止的条件是参数。

template<class T>
void Show(T val)
{cout << val << endl;
}
template<class T ,class ... Args> 
void Show(T val ,Args ... args)
{cout << val << " ";Show(args...);
}
void test_03()
{Show(1);Show(1,"x");Show(1, "x", 1.3);
}

如图,上面通过两个重载函数来实现参数包的展开,参数大于1会优先匹配void Show(T val ,Args ... args);当参数等于1的时候就去匹配void Show(T val),此时递归结束。

数组展开参数包

template<class T>
int Show(T val)
{cout << val << " ";return 0;
}
template<class ... Args> 
void Show(Args ... args)
{int arr[] = { Show(args)... };cout << endl;
}
void test_03()
{Show(1);Show(1,"x");Show(1, "x", 1.3);
}

int arr[] = { Show(args)... };数组元素个数是没有给定的所以需要通过对数组元素进行计数,此时就需要将参数包展开;


移动构造和移动赋值

C++11新增了两个默认成员函数:移动构造和移动赋值。

移动构造和移动赋值都属于移动语义,其是为了解决对于返回值的参数无法直接引用问题。

无析构函数+无拷贝构造+无赋值重载+无移动构造的情况下,编译器会生成默认移动构造:对于内置类型进行浅拷贝,对于内置类型会去调用其自己的拷贝构造。

移动赋值也同理。

一般要写析构函数的内是深拷贝的类,需要写拷贝构造和赋值重载;


包装器

C++11引入了包装器function,通过包装器可以实现将函数,仿函数以及lambda表达式类型统一。

void Print1()
{cout << "hello world" << endl;
}
struct Print2
{void operator()(){cout << "hello world" << endl;}
};
void test_04()
{auto Print3 = [] {cout << "hello world" << endl; };cout << typeid(Print1).name() << endl;cout << typeid(Print2()).name() << endl;cout << typeid(Print3).name() << endl;
}

以上三个可调用对象实现的功能都是一样的,此处可以使用typeid().name打印出其三个可调用对象的类型。

可以看出三者类型是完全不同的,C++11引入了包装器function使得可以通过函数返回值,参数将不同的可调用对象类型统一。

function<void()> arr[] = { Print1,Print2(),Print3 };

以上将三个可调用对象都放入到了数组中,其类型都是function<void()>,关于function的使用方法就是:function<函数返回值(函数参数)>,function使用时的头文件是<functional>。

包装器function的本质是一个适配器,可以对函数指针,仿函数以及lambda表达式进行包装。


绑定bind

对于库中的有些接口,参数传递很多并且有些参数是固定的;此时就可以通过bind绑定将接口参数进行绑定。

double RAdd(int x, int y, double rate)
{return (x + y) * rate;
}void test_05()
{//如果rate始终是固定的,不需要进行修改次数就可以使用绑定bindauto RAdd2 = bind(RAdd, placeholders::_1, placeholders::_2, 0.54);cout << RAdd2(10, 4) << endl;
}

bind的参数:可调用对象;参数匹配的位置:10就和_1位置匹配,4就和_2位置匹配,_1和_2有分别和函数参数匹配即x和y;

通过对_1和_2位置的调换,可以出现不同的结果。

如下图所示:通过对_1和_2位置的调换可能会导致函数的调用发生变化。

 补充:对于类成员函数的绑定是不同的:对于非静态成员函数要加&,并且要给出对象或对象地址;对于静态成员函数可以不加&,但是建议加上。

class A
{
public:static int Add1(int x, int y){return x + y;}int Add2(int x, int y){return x + y;}private:int _a;
};void test_05()
{//非静态成员函数的绑定auto CAdd1 = bind(&A::Add2, A(), placeholders::_1, placeholders::_2);A aa;auto CAdd2 = bind(&A::Add2, &aa, placeholders::_1, placeholders::_2);//静态成员函数的绑定auto CAdd3 = bind(&A::Add1, placeholders::_1, placeholders::_2);}

智能指针

C++中对于错误的处理是使用抛异常的方式解决的,抛异常就会导致进程流被修改,当进程流改变后,原本需要释放的内存没有走到delete就会导致内存泄漏。

为了解决这一问题可以采用多次抛异常,在抛异常前进行空间的释放,如果一个函数中有多个位置进行了空间开辟,当抛异常后还需要考虑哪一个需要释放,这就导致了情况多,代码繁琐的问题。 

能不能一个空间开辟后,出作用域就销毁呢???此时就可以使用智能指针来实现。

 智能指针通过将指针交给对象,让对象进行资源的管理,在对象出作用域时调析构函数进行资源的释放。

template<class T>
class Ptr
{
public:Ptr(T* ptr):_ptr(ptr){}Ptr(const Ptr& p):_ptr(p._ptr){}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}~Ptr(){delete _ptr;}
private:T* _ptr;
};

以上是对智能指针的简单模拟实现,但是在使用的时候,对指针进行拷贝构造时就会出现对同一块区域的多次释放。在C++中有不同的智能指针,不同的指针处理方式也是不同的。 

RAII

资源获取即初始化,利用对象生命周期来控制资源,在构造函数时获取资源,在对象析构时销毁资源。

优势:1)不需要显式释放空间,出作用域自动销毁;

2)对象所需的资源在其生命周期类持续有效;

auto_ptr

auto_ptr是C++98时推出的一个智能指针;auto_ptr对于指针拷贝的方法是:将空间的管理权转移,在完成拷贝构造之后,将被拷贝对象置空。其底层实现如下:

template<class T>
class auto_ptr
{
public:auto_ptr(T* ptr):_ptr(ptr){}auto_ptr(const auto_ptr& p):_ptr(p._ptr){p._ptr = nullptr;}auto_ptr operator=(const auto_ptr& p){_ptr = p._ptr;p._ptr = nullptr;return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}~auto_ptr(){delete _ptr;}
private:T* _ptr;
};

可以看到,在拷贝完成后,被拷贝对象悬空导致其无法使用,这使得auto_ptr不被广泛使用。

unique_ptr

unique_ptr对于拷贝和赋值的处理方法更加暴力,unique_ptr不支持赋值和拷贝构造。

所以在实现的时候,需要将拷贝和赋值只声明不定义,并且置为私有防止其在外面被定义,为防止编译器自动生成在函数后面加上delete。

template<class T>
class unique_ptr
{
public:unique_ptr(T* ptr):_ptr(ptr){}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}~unique_ptr(){delete _ptr;}
private:unique_ptr(const unique_ptr& p) = delete;unique_ptr operator=(const unique_ptr& p) = delete;T* _ptr;
};

shared_ptr

shared_ptr通过对指向每个空间的指针进行计数来实现对空间的释放,当一个指向一个空间的指针数量为0是对空间进行释放;

所以shared_ptr需要添加一个成员变量来实现计数。

template<class T>
class shared_ptr
{
public:shared_ptr(T* ptr):_ptr(ptr),_pcount(new int(1)){}shared_ptr(const shared_ptr& p):_ptr(p._ptr),_pcount(p._pcount){++(*_pcount);}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}shared_ptr operator=(const shared_ptr& p){_ptr = p._ptr;_pcount = p._pcount;++(*_pcount);return *this;	}~shared_ptr(){if (--(*_pcount) == 0){delete _ptr;}}
private:T* _ptr;int* _pcount;
};

shared_ptr确实解决了何时释放的问题,但是又出现了循环引用的问题。

循环引用

当一个对象有前后指针的时候就会出现问题,比如一下代码。

template<class T>
struct Node
{Node():_a(T()),_next(nullptr),_prev(nullptr){ }T _a;shared_ptr<Node> _next;shared_ptr<Node> _prev;
};void test_06()
{shared_ptr<Node<int>> aa(new Node<int>);shared_ptr<Node<int>> bb(new Node<int>);aa->_next = bb;bb->_prev = aa;
}

当aa的后继指针指向bb的时候,bb的引用计数就变成了2,同理aa的引用计数也编程了2。当对aa进行销毁的时候,其引用计数是2无法调用Node的析构,也就不能进行_next和_prev的析构了,此时就出现了空间泄露。

为了解决这一问题添加了weak_ptr。

weak_ptr

weak_ptr与shared_ptr的使用是一样的,只是在对shared_ptr拷贝的时候不会对引用计数进行改变。weak_ptr不遵循RAII,其是专门为解决循环引用而出现的。

template<class T>
class weak_ptr
{
public:weak_ptr(T* ptr):_ptr(ptr){}weak_ptr(const shared_ptr<T>& p):_ptr(p._ptr){}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}weak_ptr operator=(const shared_ptr<T>& p){_ptr = p._ptr;return *this;}
private:T* _ptr;
};

上面Node类定义变为:

template<class T>
struct Node
{Node():_a(T()),_next(nullptr),_prev(nullptr){ }T _a;weak_ptr<Node> _next;weak_ptr<Node> _prev;
};

补充

shared_ptr<int> aa(new int[10]);

当我们开辟一个数组的空间时,释放时再使用delete就不能进行空间释放了,所以对于shared_ptr和unique_ptr的参数增加了一个:释放对象。

结合lambda表达式使用起来更加简单。Del的类型可以使用function表示。

template<class T, class Del=function<void(T*)>>
class shared_ptr
{
public:shared_ptr(T* ptr, Del del = [](T* ptr) {delete ptr; }):_ptr(ptr),_pcount(new int(1)),_del(del){}shared_ptr(const shared_ptr<T>& p):_ptr(p._ptr),_pcount(p._pcount){++(*_pcount);}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}shared_ptr operator=(const shared_ptr<T>& p){_ptr = p._ptr;_pcount = p._pcount;++(*_pcount);return *this;}~shared_ptr(){if (--(*_pcount) == 0){_del(_ptr);}}
private:T* _ptr;int* _pcount;Del _del;
};
shared_ptr<int> a(new int[10], [](int* ptr) {delete[] ptr; });
shared_ptr<FILE> b(fopen("test.txt", "w"), [](FILE* ptr) {fclose(ptr); });

总结

auto_ptr:管理权转移,被拷贝的对象会悬空;

unique_ptr:不支持赋值和拷贝构造;

shared_ptr:通过引用计数控制内存的释放;

weak_ptr:解决shared_ptr的循环引用问题,拷贝和赋值的时候不增加引用计数。


特殊类的设计

不能被拷贝的类

C++11增加了delete的功能,不仅能对new的空间进行释放,放在默认成员函数后面还能表示:不让编译器生成该函数。

实现:将拷贝和赋值置为私有,且使用delete不让编译器生成即可。

template<class T>
class NoCopy
{
public://...
private:NoCopy(const NoCopy&) = delete;NoCopy operator=(const NoCopy&) = delete;T _val;
};

只能在堆上创建类

也就是不能再栈上创建对象,栈上创建对象必须能够调用构造函数和析构函数,所以对于类的实现有两种方法:1)将构造函数私有;2)将析构函数私有;还需要将拷贝构造和赋值删除。

将构造函数私有

将构造函数私有之后,new也不能调用构造函数了,所以需要增加接口专门返回在对上创建的对象。

template<class T>
class HeapOnly
{static HeapOnly* Get(){return new HeapOnly;}private:HeapOnly(const HeapOnly&) = delete;HeapOnly operator=(const HeapOnly&) = delete;HeapOnly(){//...}T _val;
};

将析构函数私有

将析构函数私有之后,还需要提供接口进行空间的释放。

template<class T>
class HeapOnly
{HeapOnly(){//...}private:~HeapOnly(){//...}HeapOnly(const HeapOnly&) = delete;HeapOnly operator=(const HeapOnly&) = delete;T _val;
};

只能在栈上创建对象

对于只能在栈上创建对象,就需要不能让new正常使用,new分为两步:1)调用operator new;2)调用构造函数;

实现:重载operator new,将其删除并将构造函数私有;向外提供构造接口。

template<class T>
class StackOnly
{static StackOnly Creat(){StackOnly st;return st;}~StackOnly(){//...}
private:void* operator new(size_t size) = delete;StackOnly(){//...}T _val;
};

 只能创建一个对象(单例模式)

创建一个类只能创建一个对象,这中类称为单例模式。

实现方法:1)只创建一个对象,将这个对象设为类的及静态成员,在每次获取的时候都将这一静态成员返回;2)将构造函数设为私有,防构造;3)防拷贝,将拷贝和赋值删除。

该类分为两种:饿汉模式和懒汉模式。

饿汉模式

饿汉模式指的是在main函数之前就创建出对象。

class Hungry_class
{
public:Hungry_class& Get(){return _date;}private:Hungry_class(const Hungry_class&) = delete;Hungry_class operator=(Hungry_class) = delete;Hungry_class(){//...}static Hungry_class _date;
};
Hungry_class Hungry_class::_date;

函数自始至终都只有一个对象_date。

饿汉模式的劣势:

1)在main函数之前就进行对象的创建,当有多个单例模式需要被创建时就会影响程序的启动效率。

2)如果两个单例类A和B之间相互联系,B的创建需要A,如果还是使用饿汉模式就会导致无法控制哪一个单例对象先创建。

懒汉模式

懒汉模式与饿汉不同的是:懒汉模式是在需要单例对象时才去创建。

实现方法:与饿汉模式一样,但是懒汉的成员变量是指针而不是对象。

class Lazy_class
{
public:Lazy_class& Get(){if (_date == nullptr){Lazy_class* _date = new Lazy_class;}return *_date;}private:Lazy_class(const Lazy_class&) = delete;Lazy_class operator=(Lazy_class) = delete;Lazy_class(){//...}T _val;static Lazy_class* _date;
};
Lazy_class* Lazy_class::_date;

单例对象的释放

一般单例对象是不需要进行释放的,但是如果中途需要进行显示释放或程序需要进行一些特殊动作(如持久化)等;

单例对象通常是在多个进程中使用的,所以单例对象的释放不能简单的根据作用域让其自己释放,需要提供专门的接口释放。

单例模式析构可以手动调用,也可以像智能指针一样自动调用。

可以通过设计一个内部类实现自动调用析构函数。

class Lazy_class
{
public:static Lazy_class& Get(){if (_date == nullptr){Lazy_class* _date = new Lazy_class;}return *_date;}static void Destory(){//...}struct GC{~GC(){Lazy_class::Destory();}};private:Lazy_class(const Lazy_class&) = delete;Lazy_class operator=(Lazy_class) = delete;Lazy_class(){//...}static Lazy_class* _date;static GC _gc;
};
Lazy_class* Lazy_class::_date;
Lazy_class::GC Lazy_class::_gc;

相关文章:

C++11特性补充

目录 lambda表达式 定义 捕捉的方式 可变模板参数 递归函数方式展开参数包 数组展开参数包 移动构造和移动赋值 包装器 绑定bind 智能指针 RAII auto_ptr unique_ptr shared_ptr 循环引用 weak_ptr 补充 总结 特殊类的设计 不能被拷贝的类 只能在堆上创建…...

缓存 --- Redis性能瓶颈和大Key问题

缓存 --- Redis性能瓶颈和大Key问题 内存瓶颈网络瓶颈CPU 瓶颈持久化瓶颈大key问题优化方案 Redis 是一个高性能的内存数据库&#xff0c;但在实际使用中&#xff0c;可能会在内存、网络、CPU、持久化、大键值对等方面遇到性能瓶颈。下面从这些方面详细分析 Redis 的性能瓶颈&a…...

css3新特性第三章(文本属性)

一、文本属性 文本阴影文本换行文本溢出文本修饰文本描边 1.1 文本阴影 在 CSS3 中&#xff0c;我们可以使用 text-shadow 属性给文本添加阴影。 语法&#xff1a; text-shadow: h-shadow v-shadow blur color; 值描述h-shadow必需写&#xff0c;水平阴影的位置。允许负值。…...

Redis 缓存—处理高并发问题

Redis的布隆过滤器、单线程架构、双写一致性、比较穿透、击穿及雪崩、缓存更新方案及分布式锁。 1 布隆过滤器 是一种高效的概率型数据结构&#xff0c;用于判断元素是否存在。主要用于防止缓存穿透&#xff0c;通过拦截不存在的数据查询&#xff0c;避免击穿数据库。 原理&…...

嵌入式芯片中的 SRAM 内容细讲

什么是 RAM&#xff1f; RAM 指的是“随机存取”&#xff0c;意思是存储单元都可以在相同的时间内被读写&#xff0c;和“顺序访问”&#xff08;如磁带&#xff09;相对。 RAM 不等于 DRAM&#xff0c;而是一类统称&#xff0c;包括 SRAM 和 DRAM 两种主要类型。 静态随机存…...

实操基于MCP驱动的 Agentic RAG:智能调度向量召回或者网络检索

我们展示了一个由 MCP 驱动的 Agentic RAG&#xff0c;它会搜索向量数据库&#xff0c;当然如果有需要他会自行进行网络搜索。 为了构建这个系统&#xff0c;我们将使用以下工具&#xff1a; 博查搜索 用于大规模抓取网络数据。作为Faiss向量数据库。Cursor 作为 MCP 客户端。…...

位运算---总结

位运算 基础 1. & 运算符 : 有 0 就是 0 2. | 运算符 : 有 1 就是 1 3. ^ 运算符 : 相同为0 相异为1 and 无进位相加位运算的优选级 不用在意优先级,能加括号就加括号给一个数 n ,确定它的二进制位中第 x 位是 0 还是 1? 规定: 题中所说的第x位指:int 在32位机器下4个…...

从0开始搭建一套工具函数库,发布npm,支持commonjs模块es模块和script引入使用

文章目录 文章目标技术选型工程搭建1. 初始化项目2. 安装开发依赖3. 项目结构4. 配置文件tsconfig.json.eslintrc.jseslint.config.prettierrc.jsrollup.config.cjs创建 .gitignore文件 设置 Git 钩子创建示例工具函数8. 版本管理和发布9 工具函数测试方案1. 安装测试依赖2. 配…...

精通 Spring Cache + Redis:避坑指南与最佳实践

Spring Cache 以其优雅的注解方式&#xff0c;极大地简化了 Java 应用中缓存逻辑的实现。结合高性能的内存数据库 Redis&#xff0c;我们可以轻松构建出响应迅速、扩展性强的应用程序。然而&#xff0c;在享受便捷的同时&#xff0c;一些常见的“坑”和被忽视的最佳实践可能会悄…...

DSP28335入门学习——第一节:工程项目创建

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.20 DSP28335开发板学习——第一节&#xff1a;工程项目创建 前言开发板说明引用解答…...

Docker Registry(镜像仓库)

官方架构 Docker 使用客户端 - 服务器 (C/S) 架构模式&#xff0c;使用远程 API 来管理和创建 Docker 容器。Docker 容器通过 Docker 镜像来创建。 Docker 仓库(Registry)&#xff1a;Docker 仓库用来保存镜像&#xff0c;可以理解为代码控制中的代码仓库。Docker Hu…...

通过Dify快速搭建本地AI智能体开发平台

1. 安装Docker Desktop 访问 Docker官网 点击Download Docker Desktop&#xff0c;直接按照官方要求来就可以。 # 这串命令就像魔法咒语&#xff0c;在黑色窗口&#xff08;命令提示符&#xff09;里输入就能检查安装是否成功 docker --version2.安装dify 3.运行 Ollama 大…...

计算机视觉与深度学习 | Transformer原理,公式,代码,应用

Transformer 详解 Transformer 是 Google 在 2017 年提出的基于自注意力机制的深度学习模型,彻底改变了序列建模的范式,解决了 RNN 和 LSTM 在长距离依赖和并行计算上的局限性。以下是其原理、公式、代码和应用的详细解析。 一、原理 核心架构 Transformer 由 编码器(Encod…...

skywalking agent 关联docker镜像

Apache SkyWalking 提供了多种方式来部署和使用 SkyWalking Agent&#xff0c;包括在 Docker 容器中运行的应用。虽然 SkyWalking Agent 本身不是一个独立的 Docker 镜像&#xff0c;但你可以通过几种方式将 SkyWalking Agent 集成到你的 Docker 应用中。 方式一&#xff1a;手…...

【中间件】nginx将请求负载均衡转发给网关,网关再将请求转发给对应服务

一、场景 前端将请求发送给nginx&#xff0c;nginx将请求再转发给网关&#xff0c;网关再将请求转发至对应服务。由于网关会部署在多台服务器上&#xff0c;因此nginx需要负载均衡给网关发请求。nginx所有配置均参照官方文档nginx开发文档&#xff0c;可参考负载均衡板块内容 二…...

Milvus(1):什么是 Milvus

Milvus 由 Zilliz 开发&#xff0c;并很快捐赠给了 Linux 基金会下的 LF AI & Data 基金会&#xff0c;现已成为世界领先的开源向量数据库项目之一。它采用 Apache 2.0 许可发布&#xff0c;大多数贡献者都是高性能计算&#xff08;HPC&#xff09;领域的专家&#xff0c;擅…...

第十六节:高频开放题-React与Vue设计哲学差异

响应式原理&#xff08;Proxy vs 虚拟DOM&#xff09; 组合式API vs Hooks React 与 Vue 设计哲学差异深度解析 一、响应式原理的底层实现差异 1. Vue 的响应式模型&#xff08;Proxy/数据劫持&#xff09; Vue 的响应式系统通过 数据劫持 实现自动依赖追踪&#xff1a; • …...

【Hot100】 240. 搜索二维矩阵 II

目录 引言搜索二维矩阵 II我的解题贪心求解解题思路详解搜索策略&#xff08;以从右上角开始为例&#xff09;为什么这种方法有效&#xff1f; 完整代码实现复杂度分析示例演示 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a…...

每日面试实录·携程·社招·JAVA

&#x1f4cd;面试公司&#xff1a;携程 &#x1f45c;面试岗位&#xff1a;后端开发工程师&#xff08;社招&#xff09; &#x1f550;面试时长&#xff1a;约 50 分钟 &#x1f504;面试轮次&#xff1a;第 1 轮技术面 ✨面试整体节奏&#xff1a; 这场携程的社招 Java 一面…...

Oracle--用户管理

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 用户管理在 Oracle 数据库中至关重要。一个服务器通常只运行一个 Oracle 实例&#xff0c;而一个 Oracle 用户代表一个用户群&#xff0c;他们通过该用…...

20.3 使用技巧5

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 20.3.8 CellContentClick事件 当增加新按钮列或者超链接列后&#xff0c;按钮或者超链接&#xff0c;会发现&#xff0c;按钮或者超链…...

Kubernetes相关的名词解释Metrics Server组件(7)

什么是Metrics Server&#xff1f; Metrics Server 是 Kubernetes 集群中的一个关键组件&#xff0c;主要用于资源监控和自动扩缩容。 kubernetes 从1.8版本开始不再集成cadvisor&#xff0c;也废弃了heapster&#xff0c;使用metrics server来提供metrics。那么...... 什么…...

17.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--SonarQube部署与配置

在将孢子记账系统从单体架构转向微服务架构的过程中&#xff0c;代码质量的管理变得尤为重要。随着项目规模的扩大和团队协作的深入&#xff0c;我们需要一个强大的工具来帮助我们持续监控和改进代码质量。我们首选SonarQube&#xff0c;它能够帮助我们识别代码中的潜在问题、技…...

计算机是如何看待数据的?

一、计算机如何“看待”数据&#xff1f; 物理层本质&#xff1a; 计算机的所有数据最终以二进制&#xff08;0和1&#xff09;在电路中表示&#xff08;高电平1&#xff0c;低电平0&#xff09;。 无论你用何种进制描述数据&#xff08;如十六进制 0xA1 或十进制 161&#xf…...

25.4.20学习总结

如何使用listView组件来做聊天界面 1. 什么是CellFactory&#xff1f; 在JavaFX中&#xff0c;控件&#xff08;比如ListView、TableView等&#xff09;用Cell来显示每一条数据。 Cell&#xff1a;代表这个单元格&#xff08;即每个列表项&#xff09;中显示的内容和样式。 …...

SpringBoot3集成ES8.15实现余额监控

1. gradle依赖新增 implementation org.springframework.boot:spring-boot-starter-data-elasticsearch implementation co.elastic.clients:elasticsearch-java:8.15.02. application.yml配置 spring:elasticsearch:uris: http://localhost:9200username: elasticpassword: …...

STM32基础教程——串口收发

目录 前言 字长设置 ​编辑 停止位 起始位侦测 波特率 1. UART波特率的基本原理 2. 为什么需要先除以分频因子&#xff08;USARTDIV&#xff09;&#xff1f; &#xff08;1&#xff09;PCLK频率太高 &#xff08;2&#xff09;分频因子的作用 3. 为什么还需要再除以…...

Matlab 步进电机传递函数模糊pid

1、内容简介 Matlab 210-步进电机传递函数模糊pid 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...

unordered_map、unordered_set详解

深入理解C中的 unordered_map 和 unordered_set 在C标准库中&#xff0c;unordered_map 和 unordered_set 是两个基于‌哈希表&#xff08;Hash Table&#xff09;‌实现的高效容器。它们以‌O(1)‌的平均时间复杂度实现快速查找、插入和删除操作&#xff0c;特别适合需要高频…...

详解trl中的GRPOTrainer和GRPOConfig

引言 在大型语言模型(LLM)的强化学习微调领域, Group Relative Policy Optimization (GRPO) 算法因其高效性和资源友好性受到广泛关注。Hugging Face的 TRL (Transformer Reinforcement Learning) 库通过GRPOTrainer和GRPOConfig提供了该算法的开箱即用实现。本文将深入解析…...

【C++】多态 - 从虚函数到动态绑定的核心原理

&#x1f4cc; 个人主页&#xff1a; 孙同学_ &#x1f527; 文章专栏&#xff1a;C &#x1f4a1; 关注我&#xff0c;分享经验&#xff0c;助你少走弯路 文章目录 1. 多态的概念2. 多态的定义及实现2.1 多态的构成条件2.1.1实现多态还有两个必须重要条件&#xff1a;2.1.2 虚…...

项目预期管理:超越甘特图,实现客户价值交付

引言 在项目管理实践中&#xff0c;许多项目经理习惯于将注意力集中在甘特图的进度条上&#xff0c;关注任务是否按时完成、里程碑是否达成。然而&#xff0c;这种以计划管理为中心的方法往往忽略了项目管理的核心目标&#xff1a;满足客户预期&#xff0c;交付真正的价值。项…...

FISCO 2.0 安装部署WeBASE与区块链浏览器(环境搭建)

FISCO BCOS 2.0 安装部署WeBASE与区块链浏览器-对应的官网地址&#xff1a; WeBASE平台&#xff1a;https://webasedoc.readthedocs.io/zh-cn/latest/docs/WeBASE/install.html 区块链浏览器&#xff1a;https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/docs/br…...

xss学习3之服务端session

一、服务端的Session 1. cookie和session 1&#xff09;cookie和session对比 cookie: 保存在客户端&#xff0c;包含所有key-value信息&#xff0c;浏览器访问多个网站时会积累大量cookie&#xff0c;占用存储空间&#xff0c;并在每次请求时携带所有cookie&#xff0c;增加…...

23种设计模式-结构型模式之适配器模式(Java版本)

Java 适配器模式&#xff08;Adapter Pattern&#xff09;详解 &#x1f50c; 什么是适配器模式&#xff1f; 适配器模式用于将一个类的接口转换成客户端所期望的另一种接口&#xff0c;让原本接口不兼容的类可以协同工作。 &#x1f4e6; 就像插头转换器&#xff0c;让不同…...

【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的

HTTP与HTTPS全面对比及HTTPS加密流程详解 一、HTTP与HTTPS核心区别 特性HTTPHTTPS协议基础明文传输HTTP SSL/TLS加密层默认端口80443加密方式无加密混合加密&#xff08;非对称对称&#xff09;证书要求不需要需要CA颁发的数字证书安全性易被窃听、篡改、冒充防窃听、防篡改…...

使用安全继电器的急停电路设计

使用安全继电器的急停电路设计 一&#xff0c;急停回路的设计1&#xff0c;如何将急停接到线路当中&#xff1f;2&#xff0c;急停开关 如何接到安全继电器中 一&#xff0c;急停回路的设计 急停是每一个设备必不可少的部分&#xff0c;因为关乎安全&#xff0c;所以说所以说他…...

SpringCloud概述和环境搭建

SpringCloud概述和环境搭建 一.微服务的引入1.单体架构2.集群和分布式架构3.集群和分布式4.微服务架构4.微服务的优缺点 二.微服务解决方案-SpringCloud1.Spring Cloud简介2.Spring Cloud版本3.Spring Cloud实现方案4.Spring Cloud Alibaba 三.环境搭建1.安装JDK172.Ubantu上下…...

System.out 详解

System.out 详解 System.out 是 Java 提供的标准输出流(PrintStream 类型),默认关联控制台(Console),用于向终端打印文本信息。它是 Java 中最常用的输出方式之一,尤其在调试和命令行程序开发中。 1. 核心知识点 (1)System.out 的本质 类型:PrintStream(字节流,但…...

每天学一个 Linux 命令(28):ln

​​可访问网站查看,视觉品味拉满: http://www.616vip.cn/28/index.html ln 是 Linux 中用于创建文件或目录链接的命令,主要生成硬链接(Hard Link)和符号链接(Symbolic Link,软链接)。链接常用于文件共享、快捷访问或版本管理。 命令格式 ln [选项] 源文件 目标链接链…...

【微知】服务器如何获取服务器的SN序列号信息?(dmidecode -t 1)

文章目录 背景命令dmidecode -t的数字代表的字段 背景 各种场景都需要获取服务器的SN&#xff08;Serial Number&#xff09;&#xff0c;比如问题定位&#xff0c;文件命名&#xff0c;该部分信息在dmi中是标准信息&#xff0c;不同服务器&#xff0c;不同os都能用相同方式获…...

4.20刷题记录(单调栈)

第一部分&#xff1a;简单介绍 单调栈我的理解是在栈中存储数字出现的位置&#xff0c;然后通过遍历比较当前栈顶元素与当前元素的大小关系&#xff0c;从而确定逻辑相关顺序。 第二部分&#xff1a;真题讲解 &#xff08;1&#xff09;739. 每日温度 - 力扣&#xff08;Lee…...

Opencv图像处理:模板匹配对象

文章目录 一、模板匹配1、什么是模板匹配&#xff1f;2、原理 二、单模板匹配&#xff08;代码实现&#xff09;1、预处理2、 开始模板匹配并绘制匹配位置的外接矩形 三、多模板匹配&#xff08;代码实现&#xff09;1、读取图片和模板2、模板匹配3、设置阈值1&#xff09;阈值…...

Web3.0热门领域NFT项目实战课程

课程大小&#xff1a;3.8G 课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/90616383 更多资源下载&#xff1a;关注我 深度掌握Solidity合约开发&#xff0c;助力成为抢手的Web3.0开发工程师 深入Web3.0技术的人才&#xff0c;一将难求。本课程由We…...

DAY 50 leetcode 1047--栈和队列.删除字符串中的所有相邻重复项

题号1047 给出由小写字母组成的字符串 s&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 s 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 import java.util.Ar…...

单例模式与消费者生产者模型,以及线程池的基本认识与模拟实现

前言 今天我们就来讲讲什么是单例模式与线程池的相关知识&#xff0c;这两个内容也是我们多线程中比较重要的内容。其次单例模式也是我们常见设计模式。 单例模式 那么什么是单例模式呢&#xff1f;上面说到的设计模式又是什么&#xff1f; 其实单例模式就是设计模式的一种。…...

微信小程序通过mqtt控制esp32

目录 1.注册巴法云 2.设备连接mqtt 3.微信小程序 备注 本文esp32用的是MicroPython固件&#xff0c;MQTT服务用的是巴法云。 本文参考巴法云官方教程&#xff1a;https://bemfa.blog.csdn.net/article/details/115282152 1.注册巴法云 注册登陆并新建一个topic&#xff…...

QML、Qt Quick 、Qt Quick Controls 2

一、概念 基本关系 QML 是声明式语言,用于描述用户界面。声明式语法(类似JSON+JavaScript),定义UI结构和行为。 Qt Quick 是 QML 的标准库,提供基本类型和功能。提供QML语言运行时的基础能力,相当于QML的"标准模板库(STL)"。 Quick Controls 2 是基于 Qt Quic…...

基于maven-jar-plugin打造一款自动识别主类的maven打包插件

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

利用 HEMT 和 PHEMT 改善无线通信电路中的增益、速度和噪声

本文要点 高电子迁移率晶体管 &#xff08;High electron mobility transistors &#xff0c;HEMTs&#xff09; 和应变式异质接面高迁移率晶体管&#xff08;pseudomorphic high electron mobility transistors &#xff0c;PHEMTs&#xff09; 因其独特的、可提高性能的特点而…...