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

主题网站开发介绍/浙江网络推广公司

主题网站开发介绍,浙江网络推广公司,做暧暧小视频网站,傻瓜使用模板建网站智能指针 1. 垃圾回收 垃圾回收机制已经大行其道,得到了诸多编程语言的支持,例如Java、Python、 C#、PHP等。而C虽然从来没有公开得支持过垃圾回收机制,但C98/03标准中,支持使用auto_ptr智能指针来实现堆内存的自动回收; C11新标…

智能指针

1. 垃圾回收

垃圾回收机制已经大行其道,得到了诸多编程语言的支持,例如Java、Python、
C#、PHP等。而C++虽然从来没有公开得支持过垃圾回收机制,但C++98/03标准中,支持使用auto_ptr智能指针来实现堆内存的自动回收; C++11新标准在废弃auto_pt的同时,增添了unique_ptr、shared_ptr以及weak_ptr这3个智能指针来实现堆内存的自动回收。

所谓智能指针,可以从字面上理解为“智能”的指针。具体来讲,智能指针和普通指针的用法是相似的,不同之处在于,智能指针可以在适当时机自动释放分配的内存。

也就是说,使用智能指针可以很好地避免“忘记释放内存而导致内存泄漏”问题出现。由此可见,C++也逐渐开始支持垃圾回收机制了。

2. 智能指针

C++中的智能指针是一种用于管理动态分配内存的资源对象。它们能够自动地跟踪资源的所有权,当资源不再需要时,会自动释放它们,从而避免内存泄漏和悬挂指针等问题。C++标准库提供了三种主要类型的智能指针:std::shared_ptrstd::unique_ptrstd::weak_ptr,智能指针都是通过类模板的方式实现的。

std::shared_ptrstd::unique_ptr,还有 std::weak_ptr。这三种智能指针在不同的情况下具有不同的用途和语义。

  1. std::shared_ptr:多个 std::shared_ptr 对象可以共享同一个资源的所有权。资源只有在最后一个引用计数归零时才会被释放。
  2. std::unique_ptrstd::unique_ptr 表示独占所有权,一个资源只能由一个 std::unique_ptr 拥有。这种指针在需要确保只有一个拥有者时非常有用。
  3. std::weak_ptrstd::weak_ptr 是一种弱引用指针,用于解决 std::shared_ptr 循环引用问题。std::weak_ptr 可以与 std::shared_ptr 共同使用,但不会增加资源的引用计数,从而避免循环引用导致的内存泄漏。

这三种智能指针类型提供了灵活的内存管理选项,可以根据具体的需求选择适当的类型来管理资源。

2.1 shared_ptr

shared_ptr(T表示指针指向的数据类型)的定义位于头文件中,并位于std命名空间中,所以使用智能指针时,程序都需要包含下面两行代码:

#include<memory>
using namespace std;

和unique_ptr,weak_ptr不同之处在于,多个shared_ptr智能指针可以共用一块内存空间。并且,即使多个共用一块空间的shared_ptr指针中有一个指针放弃了该空间的“使用权”,也不会影响到其他指针。只有到该空间的引用次数为0时,该空间才会被释放。

因为智能指针的底层是用类模板实现的,所以智能指针的声明和初始化跟C++中的容器基本相同,下面我们来看个例子:

#include<iostream>
#include<memory>
using namespace std;int main()
{//默认初始化shared_ptr<int> p;//传参初始化//声明一个指向一块有5个int空间大小的share_ptrshared_ptr<int>p1(new int[5]);//传入空指针//空指针的引用次数为0shared_ptr<int>p2(nullptr);//使用C++11标准提供的std:make_shared<T>模板函数shared_ptr<int>p3 = make_shared<int>(5);//这段代码和第二段代码的效果相同return 0;
}

在初始化shared_ptr指针时,还可以自定义所指内存的释放规则,这样当内存的引用次数为0时,会优先调用自定义的释放规则。

在某些场景中,自定义释放规则是很用必要的。比如,对于申请的动态数组来说,shared_ptr指针默认的释放规则是不支持释放数组的,只能自定义对应的释放规则,才能正确释放动态开辟的内存。

当然,对于申请的动态数组来说,释放规则可以使用C++标准中提供的default_delete模板类,不过,我们也可以自定义释放规则。

废话不多说,我们直接上代码:

#include<iostream>
#include<memory>
using namespace std;void DeleteInt(int* p)
{delete[]p;
}int main()
{//使用内置的default_delete作为释放规则shared_ptr<int>p4(new int[5], default_delete<int[]>());//初始化智能指针,并自定义规则shared_ptr<int>p5(new int[5], DeleteInt);//使用lambda表达式shared_ptr<int>p6(new int [5], [](int* p) {delete[]p; });return 0;
}

2.2 unique_ptr

unique_ptr指针自然也具备“在适当时机自动释放堆内存空间”的能力。和shared_ptr指针最大不同之处在于,unique_ptr指针指向的堆内存无法同某它unique_ptr共享,也就是说,每个unique_ptr指针都独自拥有对其所指堆内存空间的所有权。

例如:

#include <iostream>
#include <memory>int main() {std::unique_ptr<int> unique1 = std::make_unique<int>(42);// std::unique_ptr<int> unique2 = unique1; // 错误!不允许复制独占指针std::cout << "Value of unique1: " << *unique1 << std::endl;unique1.reset(); // 释放资源if (!unique) {std::cout << "unique is nullptr" << std::endl;}return 0; // 在main函数结束时,unique的资源被释放
}

2.3 weak_ptr

在 C++ 中,std::shared_ptr 允许多个智能指针共享同一个资源,它们会共同维护一个引用计数来跟踪资源的使用。这样做通常很有用,但可能导致循环引用问题,即两个或多个对象互相引用,导致它们的引用计数永远不会归零,资源永远不会释放,从而产生内存泄漏。

我们来看一个案例:

class A {
public:std::shared_ptr<B> b_ptr;
};class B {
public:std::shared_ptr<A> a_ptr;
};

在这个例子中,类 A 持有类 B 的智能指针,同时类 B 持有类 A 的智能指针。因此,它们之间形成了循环引用,即使不再需要它们,它们的引用计数也不会降到零,导致内存泄漏。

std::weak_ptr 的作用是打破这种循环引用,同时允许检查资源是否仍然存在。std::weak_ptr 不会增加资源的引用计数,它只是一个观察者,当资源被释放后,它会自动变成空指针。

下面是 std::weak_ptr 的使用示例:

#include <iostream>
#include <memory>class A;
class B;class A {
public:std::shared_ptr<B> b_ptr;A() {std::cout << "A constructor" << std::endl;}~A() {std::cout << "A destructor" << std::endl;}
};class B {
public:std::weak_ptr<A> a_weak_ptr; // 使用 std::weak_ptr 避免循环引用B() {std::cout << "B constructor" << std::endl;}~B() {std::cout << "B destructor" << std::endl;}
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->b_ptr = b;b->a_weak_ptr = a;// 输出 A 和 B 的析构函数调用// 注意:输出会在 main 函数结束时显示,资源会正确释放return 0;
}

在这个例子中,类 A 持有类 B 的 shared_ptr,而类 B 持有类 A 的 weak_ptr。当 main 函数结束时,shared_ptr 的引用计数会归零,类 A 和类 B 的析构函数会被调用,并释放资源,而不会导致内存泄漏。

总之,std::weak_ptr 是一种用于解决循环引用和避免内存泄漏的智能指针,它允许观察资源的状态而不增加引用计数。

2.4 使用智能指针的好处

  • 自动内存管理:不需要手动调用delete来释放内存,减少内存泄漏的风险。
  • 避免悬挂指针:当资源不再需要时,智能指针会自动释放资源,避免悬挂指针问题。
  • 引用计数和独占所有权:std::shared_ptrstd::unique_ptr提供了不同的所有权管理方式,根据需要选择。

总之,智能指针是C++中一种非常有用的工具,可以大大简化内存管理,提高代码的可维护性和安全性。在编写现代C++代码时,推荐优先使用智能指针来管理动态内存分配。

3 可变参数模板

C++11之前,类模板和函数模板中只能含固定数量的模板参数。

C++11的新特性可变参数能够让您创建可以接受可变参数的函数模板和类模。

下面是一个例子:

#include<iostream>
using namespace std;
//函数模板的参数个数为0到多个参数,每个参数的类型可以各不相同。
template<class...T>//args一包形参,T一包类型void func(T...args){cout<<sizeof...(args)<<endl;   //sizeof...固定语法计算获取到的模板参数个数cout<<sizeof...(T)<<endl;   //sizeof... 只能计算可变参数
}
int main()
{func(12,13,14,15);return 0;
}

这段代码中的两个 sizeof... 分别用于计算不同的东西:

  1. sizeof...(args):这行代码计算的是可变参数 args 中的参数个数。在 main 函数中,调用了 func(12,13,14,15);,所以args 包含了四个参数,因此 sizeof...(args) 会输出 4

  2. sizeof...(T):这行代码计算的是模板参数包 T 中的类型数量。在函数模板 func 中,T 是一个模板参数包,代表可变参数的类型。由于在 main 函数中传递了四个整数参数,所以 T 中包含了四个类型,因此 sizeof...(T) 会输出 4

总结一下,sizeof...(args) 计算的是可变参数的个数,而 sizeof...(T) 计算的是可变参数的类型数量,这两个值在这个例子中都是相等的,都是 4

4. 参数包和参数展开

当我们谈论参数包和参数包展开时,我们实际上在讨论可变参数模板的一部分。

参数包(Parameter Pack)

参数包是可变参数模板中的一种特殊类型,它允许你声明一个接受不定数量参数的模板函数或类。参数包的形式为 typename... Argsclass... Args,其中 Args 是参数包的名字,可以是任何有效的标识符名字。

template <typename... Args>
void MyFunction(Args... args) {// 在函数体中可以访问 Args 的参数列表
}

在这个例子中,Args 是一个参数包,它表示可以接受零个或多个参数。当你调用 MyFunction 时,你可以传递任意数量的参数给它。

参数包展开(Parameter Pack Expansion)

参数包展开是指在模板函数或类中使用参数包中的参数的过程。展开操作使用展开操作符 ... 来实现,将参数包中的参数逐个提取出来,用于函数调用、初始化列表、递归展开等操作。

示例

让我们以一个更具体的示例来说明参数包和参数包展开。假设我们有一个可变参数模板函数 PrintArgs,它可以打印任意数量的参数:

#include <iostream>
using namespace std;template <typename... Args>
void PrintArgs(Args... args) {( (cout << args << " "), ...);// 参数包展开并打印
}int main() {PrintArgs(1, 2, "Hello", 3.14);return 0;
}

在这个示例中,PrintArgs 接受不定数量的参数,并使用展开操作符将它们逐个打印出来。在 main 函数中,我们调用 PrintArgs 函数并传递了整数、字符串和浮点数等不同类型的参数,它们都被正确地打印出来。

5. 参数包展开的主要方式

参数包展开有几种不同的方式,它们在使用时具有不同的语法和应用场景。以下是一些常见的参数包展开方法以及它们的区别:

  1. 左折叠展开(Left Fold Expansion)

    左折叠展开使用括号表达式 (expr, ...) 和展开操作符 ...,将参数包中的参数从左到右展开并应用于表达式 expr。这是最常见和直观的展开方式。

    (expr, ...);
    

    例如,上面提到的 PrintArgs 示例就是使用了左折叠展开。

  2. 右折叠展开(Right Fold Expansion)

    右折叠展开使用括号表达式 (expr, ...) 和展开操作符 ...,将参数包中的参数从右到左展开并应用于表达式 expr。右折叠展开通常用于一些需要反向处理参数的情况。

    (... , expr);
    

    例如,如果你想计算参数包中所有整数的乘积,可以使用右折叠展开。

  3. 参数包展开初始化列表(Parameter Pack Expansion in Initialization Lists)

    这种展开方式允许你在初始化列表中使用参数包展开,用于初始化数组、集合、结构体等数据结构。通常在对象的构造函数中使用。

    MyClass(std::initializer_list<T>{args...}) {// 在构造函数中使用参数包展开初始化列表
    }
    

    这种展开方式在容器类和自定义数据结构的设计中非常有用。

  4. 递归展开(Recursive Expansion)

    当参数包中包含不定数量的参数,而你希望逐个处理它们时,可以使用递归展开。这通常需要一个递归函数或类来处理参数包中的每个参数。

    template <typename T>
    void ProcessArg(T arg) {// 处理参数的逻辑
    }template <typename T, typename... Rest>
    void ProcessArgs(T first, Rest... rest) {ProcessArg(first);ProcessArgs(rest...); // 递归展开
    }
    

    这种展开方式适用于需要按顺序处理参数的情况。

    递归展开是一种在模板函数或模板类中使用递归来处理参数包的方法。通常,递归展开需要两个模板函数,一个用于处理第一个参数,另一个用于处理其余的参数,并递归调用自身。

    以下是一个具体的示例,演示如何使用递归展开来打印参数包中的所有参数:

    #include <iostream>// 基本情况:处理最后一个参数
    template <typename T>
    void PrintArg(T arg) {std::cout << arg << std::endl;
    }// 递归情况:处理第一个参数并递归处理其余参数
    template <typename T, typename... Rest>
    void PrintArgs(T first, Rest... rest) {PrintArg(first);PrintArgs(rest...); // 递归展开//会陷入死递归
    }int main() {PrintArgs(1, 2, "Hello", 3.14);return 0;
    }
    

    在这个示例中,PrintArgs 函数用于处理参数包中的参数,首先调用 PrintArg 处理第一个参数,然后递归调用 PrintArgs 处理剩余的参数。这样看起来,参数包中的所有参数都会被逐个打印出来。

    但显然,忽略了一个致命的问题,递归没有终止条件,会陷入死循环。此时,为了程序顺利运行,我们需要添加一个判断条件来终止递归函数。

    那么,该怎么添加判断条件呢?

    在C++17中, 引入了 if constexpr 语句,它允许在编译时根据条件选择不同的代码分支。这对于编写更加灵活的模板代码非常有用,因为它允许你在编译时剔除不需要的代码分支,减少模板实例化的复杂性。

    我们可以通过该语句来判断条件是否终止。

    #include <iostream>// 基本情况:处理最后一个参数
    template <typename T>
    void PrintArg(T arg) {std::cout << arg << std::endl;
    }// 递归情况:处理第一个参数并递归处理其余参数
    template <typename T, typename... Rest>
    void PrintArgs(T first, Rest... rest) {PrintArg(first);if constexpr(sizeof...(rest)>0)PrintArgs(rest...); // 递归展开
    }int main() {PrintArgs(1, 2, "Hello", 3.14);return 0;
    }
    

    递归展开 和if constexpr这两个特性在编写泛型和模板代码时非常有用,能够提高代码的灵活性和性能。

这些展开方式的选择取决于你的具体需求和代码逻辑。通常,左折叠展开是最常见和最直观的选择,但在某些情况下,其他展开方式可能更合适。要根据具体情况灵活选择展开方式,以满足你的编程需求。

总之,参数包是一种允许可变参数模板处理不定数量参数的机制,而参数包展开是将参数包中的参数逐个提取出来并在代码中使用的过程。这使得可变参数模板非常强大和灵活。

相关文章:

C++的智能指针和可变参数模板详解

智能指针 1. 垃圾回收 垃圾回收机制已经大行其道&#xff0c;得到了诸多编程语言的支持&#xff0c;例如Java、Python、 C#、PHP等。而C虽然从来没有公开得支持过垃圾回收机制&#xff0c;但C98/03标准中&#xff0c;支持使用auto_ptr智能指针来实现堆内存的自动回收; C11新标…...

Docker及常用数据库安装

Docker安装常用数据库 1、Docker安装2、Mysql安装3、Redis安装4、DM安装5、Oracle安装1、Docker安装 1、确保 yum 包更新到最新yum update2、卸载旧版本(如果安装过旧版本的话)yum remove docker docker-common docker-selinux docker-engine3、安装需要的软件包, yum-util 提…...

前端使用 JavaScript 检测用户是否在线的6种方法

要检测用户是否在线&#xff0c;可以使用以下几种方法&#xff1a; 1. 使用navigator.onLine属性&#xff1a; navigator.onLine是一个布尔值&#xff0c;表示用户是否与互联网连接。当用户在线时&#xff0c;该属性的值为true&#xff0c;当用户离线时&#xff0c;该属性的值…...

Windows下Redis的安装

文章目录 一,Redis介绍二,Redis下载三,Redis安装-解压四,Redis配置五,Redis启动和关闭(通过terminal操作)六,Redis连接七,Redis使用 一,Redis介绍 远程字典服务,一个开源的,键值对形式的在线服务框架,值支持多数据结构,本文介绍windows下Redis的安装,配置相关,官网默认下载的是…...

SpringBoot第45讲:SpringBoot定时任务 - Timer实现方式

SpringBoot第45讲:SpringBoot定时任务 - Timer实现方式 定时任务在实际开发中有着广泛的用途,本文是SpringBoot第45讲,主要帮助你构建定时任务的知识体系,同时展示Timer 的schedule和scheduleAtFixedRate例子;后续的文章中我们将逐一介绍其它常见的定时任务,并与SpringBo…...

01背包(换汤不换药)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 有一个箱子容量为V&#xff08;正整数&#xff0c;0 ≤ V ≤ 20000&#xff09;&#xff0c;同时有n个物品&#xff08;0&#xff1c;n ≤ 30&#xff09;&#xff0c;每个物品有一个体积&#xf…...

c++ folly::baton

Baton folly::Baton 是 Facebook 开源的一个同步原语&#xff0c;它提供了一种简单而灵活的方式来进行线程间的同步。它属于 Folly 库&#xff0c;是 C 编程语言的一个组件。 Baton 通常用作线程间同步、等待、通知的标识符号&#xff0c;常用姿势是&#xff0c;一些线程调用…...

05.sqlite3学习——DML(数据管理:插入、更新、删除)

目录 DML&#xff08;数据管理&#xff1a;插入、更新、删除&#xff09; 插入 更新 删除整个表 语法 实例 DML&#xff08;数据管理&#xff1a;插入、更新、删除&#xff09; 数据操纵&#xff08;DML&#xff09;&#xff1a;用于增、删、改数据 作用&#xff1a;负…...

Netty-ChannelPipeline

EventLoop可以说是 Netty 的调度中心&#xff0c;负责监听多种事件类型&#xff1a;I/O 事件、信号事件、定时事件等&#xff0c;然而实际的业务处理逻辑则是由 ChannelPipeline 中所定义的 ChannelHandler 完成的&#xff0c;ChannelPipeline 和 ChannelHandler应用开发的过程…...

从入门到精通,30天带你学会C++【第六天:与或非三兄弟和If判断语句(博主目前最长文章,2514字)】(学不会你找我)

目录 前言 计算机里的真和假 与或非三兄弟 ​编辑与运算&#xff08;&&&#xff09; 具体说明表格&#xff1a; 举个栗子1&#xff1a; 或运算&#xff08;||&#xff09; 具体说明表格&#xff1a; 举个栗子2&#xff1a; 非运算&#xff08;!&#xff09…...

如何快速找出占用空间最大的文件?

分析&回答 使用 find 命令找到大于指定大小的文件&#xff1a; 当前目录大于500M文件 find ./ -size 500M用户目录大于500M文件 find ~ -type f -size 500M根目录大于500M文件 find / -type f -size 500M 复制代码 让文件按大小排序 du -h * | sort -n 喵呜面试助手&am…...

算法:分治思想处理归并递归问题

文章目录 算法原理实现思路典型例题排序数组数组中的逆序对计算右侧小于当前元素的个数 总结 算法原理 利用归并思想进行分治也是很重要的一种思路&#xff0c;在解决逆序对的问题上有很大的需求空间 于是首先归并排序是首先的&#xff0c;归并排序要能写出来&#xff1a; c…...

小白学Go 基础02-了解Go语言的诞生与演进

Go语言诞生于何时&#xff1f;它的最初设计者是谁&#xff1f;它为什么被命名为Go&#xff1f;它的设计目标是什么&#xff1f;它如今发展得怎么样&#xff1f;带着这些问题&#xff0c;我们一起穿越时空&#xff0c;回到2007年9月Go语言诞生的那一历史时刻吧。 Go语言的诞生 …...

python中如何将十进制转成二进制

python中如何将十进制转成二进制 在 Python 中&#xff0c;你可以使用内置的 bin() 函数将十进制数转换为二进制表示形式。以下是使用 bin() 函数进行转换的示例&#xff1a; decimal_number 10binary_number bin(decimal_number)print(binary_number) # 输出&#xff1a;…...

数据结构--5.0.1图的存储结构

目录 一、邻接矩阵&#xff08;无向图&#xff09; 二、邻接矩阵&#xff08;有向图&#xff09; 三、邻接矩阵&#xff08;网&#xff09; 四、邻接表&#xff08;无向图&#xff09; 五、邻接表&#xff08;有向图&#xff09; ——图的存储结构相比较线性表与树来说就复…...

解决win10 wsl子系统安装的ubuntu环境中lsof,netstat命令查看端口没有任何输出的问题

最近有个以前的ssm项目需要在新电脑上运行测试一下&#xff0c;发现需要redis环境&#xff0c;看了官网说&#xff1a;有两种选择&#xff1a; 1. 要么在虚拟机比如vmware安装linux基础环境&#xff0c;然后再安装redis 2. 要么可以利用win10的wsl linux子系统安装ubuntu&…...

【OpenFeign】OpenFeign结合Hystrix和Sentinel实现熔断降级

OpenFeign可以与Hystrix和Sentinel结合使用&#xff0c;实现降级和熔断。 OpenFeign与Hystrix结合使用 使用OpenFeign需要引入OpenFeign的依赖&#xff1a; <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-sta…...

软件工程(十) 需求工程之需求开发与管理

前面我们学习到了需求工程的概念与分类,我们知道了需求工程主要分为需求开发和需求管理,但是没有说明到底该如何开发需求,有哪些方法去开发需求。到底该如何进行需求管理,又有哪些进行需求管理的方式。具体是如何去做的。下面我们将会详细进行描述。 1、需求开发 1.1、需…...

C++网狐服务器引入开源日志库spdlog

很多人对日志库不以为然&#xff0c;包括网狐这种十几年的公司都不重视&#xff0c;其实日志库记录的东西能在线上出问题时高效解决&#xff0c;特别是别人写的东西&#xff0c;人又走了&#xff0c;出了问题&#xff0c;还可以用日志分析快速解决。要是没有日志记录&#xff0…...

【C++】—— c++11之智能指针

前言&#xff1a; 本期&#xff0c;我们将要学习的是在c11中新提出的概念——异常指针&#xff01; 目录 &#xff08;一&#xff09;智能指针的引入 &#xff08;二&#xff09;内存泄漏 1、什么是内存泄漏&#xff0c;内存泄漏的危害 2、内存泄漏分类&#xff08;了解&a…...

html5——前端笔记

html 一、html51.1、理解html结构1.2、h1 - h6 (标题标签)1.3、p (段落和换行标签)1.4、br 换行标签1.5、文本格式化1.6、div 和 span 标签1.7、img 图像标签1.8、a 超链接标签1.9、table表格标签1.9.1、表格标签1.9.2、表格结构标签1.9.3、合并单元格 1.10、列表1.10.1、ul无序…...

如何在 Vue TypeScript 项目使用 emits 事件

Vue是构建出色的Web应用程序的最灵活、灵活和强大的JavaScript框架之一。Vue中最重要的概念和关键特性之一是能够促进应用程序组件之间的通信。让我们深入探讨一下Vue中的“emits”概念&#xff0c;并了解它们如何以流畅和无缝的方式实现父子组件之间的通信。 Vue中的emits是什…...

文件操作 黑马教程(04)

1.文本文件 写文件 #include "iostream" #include "fstream" using namespace std; /** 文件操作** 程序运行时产生的数据都属于临时数据&#xff0c;程序一旦结束都会被释放* 通过文件可以将数据持久化* C中对文件操作需要包含头文件<fstream>** 文…...

Jmeter(二十七):BeanShell PostProcessor跨线程全局变量使用

在性能测试中&#xff0c;两个相关联的接口不一定都在同一个线程组&#xff0c;遇见这种情况时&#xff0c;我们要进行跨线程组传参&#xff0c;此处用登录和查询配送单两个请求举例&#xff1b; 1、登录请求中配置json提取器&#xff0c;将接口返回的token保存在变量中&#…...

手写表格OCR识别并与大模型ChatGPT交互?

这是一张手写表格&#xff0c;姓名做了脱敏处理。现在需要对其识别&#xff0c;并分析。 直接粘贴剪切板中的表格原始图片&#xff0c;在网页中ctlV进行识别。识别结果列用分隔符|&#xff0c;可以直接粘贴到excel&#xff0c;进行数据列分隔。为了美观期间&#xff0c;也可以用…...

使用 v-for 指令和数组来实现在 Uni-app 中动态增减表单项并渲染多个数据

在 data 中定义一个数组&#xff0c;用于存储表单项的数据&#xff1a; data() {return {formItems: []} } 在模板中使用 v-for 指令渲染表单项&#xff1a; <template><div><div v-for"(item, index) in formItems" :key"index"><…...

xml

1.xml 1.1概述【理解】 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年&#xff0c;又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者&#xff1a; Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。 到目前为…...

Java中的动态代理(JDK Proxy VS CGLib)

前言 动态代理可以说是Java基础中一个比较重要的内容&#xff0c;这块内容关系到Spring框架中的AOP实现原理&#xff0c;所以特别写了一篇作为个人对这块知识的总结。这部分内容主要包括&#xff1a;JDK Proxy和CGLib的基本介绍、二者的实现原理、代码示例等。 什么是动态代理…...

Redis 7 第七讲 哨兵模式(sentinal)

哨兵模式 哨兵巡查监控后台master主机是否故障,如果出现故障根据投票时自动将某一个从库转换成新的主库,继续对外服务。 作用 1. 监控redis运行状态,包括master和slave 2. 当master down机,能自动将salve切换成新的master 应用场景 主从监控监控主从redis库运行的状态…...

Python入门教程 - 判断语句(二)

目录 一、布尔类型 二、比较运算符 三、if判断语句 一、布尔类型 True False result1 10 > 5 result2 10 < 5 print(result1) print(result2) print(type(result1)) True False <class bool> 二、比较运算符 ! > < > < 比较运算的结果是布尔…...