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

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 补充 总结 特殊类的设计 不能被拷贝的类 只能在堆上创建…...

PcVue助力立讯:精密制造的智能化管控实践!

PcVue助力立讯&#xff1a; 精密制造的智能化管控实践&#xff01; 客户介绍 立讯精密&#xff08;Luxshare ICT&#xff0c;股票代码&#xff1a;002475&#xff09;成立于2004年5月24日&#xff0c;专注于为消费电子产品、汽车领域产品以及企业通讯产品提供从核心零部件、…...

jmeter中文乱码问题解决

修改jmeter.properties配置文件‌ 进入JMeter安装目录的bin文件夹&#xff0c;找到jmeter.properties文件。搜索参数sampleresult.default.encodingUTF-8&#xff0c;取消注释&#xff08;删除行首的#&#xff09;&#xff0c;并将其值改为UTF-8。保存文件并‌重启JMeter‌生效…...

最新扣子空间实操指南

一、首先要先获取到内部测试的邀请码&#xff0c; 我们先打开扣子空间官网&#xff1a;https://space.coze.cn/ 输入邀请码后进入该页面&#xff1a; 它这里支持文件上传&#xff0c;扩展里面有很多插件&#xff0c;页支持MCP各种插件. 探索模式有两种&#xff0c;一种是ai自…...

Java表达式2.0

1 .数据类型转换 自动类型转换的规则 自动类型转换遵循一定的规则&#xff0c;这些规则确保了转换的合理性和安全性。以下是自动类型转换的主要规则&#xff1a; 容量小的类型自动转换为容量大的类型 Java中&#xff0c;数据类型的容量从小到大依次为&#xff1a;byte → shor…...

JavaScript 一维数组转二维数组

题目描述&#xff1a; <script>const num [1,2,3,4]const out (function(num,m,n){if(num.length ! m*n){return []}const newarr []for(let i 0;i<m;i){newarr.push(num.slice(i*n,(i1)*n))}return newarr})(num,2,2)console.log(out)</script>不使用Stri…...

WIN10重启开机不用登录,直接进入桌面

我们个人机不需要登录。 步骤1 置&#xff0c;帐户&#xff0c;登录选项&#xff0c;密码。 输入当前密码后&#xff0c;直接下一步。 再次重启&#xff0c;就会发现不需要密码了。...

JavaScript学习教程,从入门到精通,DOM节点操作语法知识点及案例详解(21)

DOM节点操作语法知识点及案例详解 一、语法知识点 1. 获取节点 // 通过ID获取 const element document.getElementById(idName);// 通过类名获取&#xff08;返回HTMLCollection&#xff09; const elements document.getElementsByClassName(className);// 通过标签名获取…...

基于ESP32 - S3实现一个ping百度的C测试程序

环境准备 安装ESP-IDF开发环境&#xff0c;可参考官方文档。确保开发环境已正确配置&#xff0c;能对ESP32 - S3进行编译和烧录。 实现思路 连接WiFi&#xff1a;让ESP32 - S3连接到一个可用的WiFi网络。初始化Ping功能&#xff1a;利用ESP-IDF提供的Ping API初始化Ping功能…...

英语学习4.15

amateur amateur &#x1f524; 读音&#xff1a;/ˈmətər/ 或 /ˈmətʃʊr/ ✅ 词性&#xff1a;名词 / 形容词 ✅ 中文释义&#xff1a; &#xff08;名词&#xff09;业余爱好者   &#x1f449; 指不是以此为职业的人&#xff0c;通常出于兴趣而从事某项活动。   …...

开源项目FastAPI-MCP:一键API转换MCP服务

在当今AI开发的世界中,应用程序与AI模型之间的无缝集成至关重要。 模型上下文协议(Model Context Protocol, MCP)通过允许AI模型访问外部工具和数据源,弥合了这一差距。 FastAPI MCP是一个强大的工具,它可以通过最少的配置将您现有的FastAPI端点转换为MCP兼容的工具。 本…...

python课堂随记

11.15 连接符 namemcl print(我叫,name) print(我叫name)#连接符 age18 print(我叫name年龄str(age)) #连接符需要数据类型相同 11.17随记 除法运算神奇 8/5 #1.6 8//5 #1 -8/5 #-1.6 -8//5 #-2 ##次方表示—两个** 3的27次方 27的3次方 小结 程序的书写&…...

Agent安装-Beszel​​ 轻量级服务器监控平台

docker-compose安装 beszel-agent 安装 docker-compose 配置文件 services:beszel-agent:image: henrygd/beszel-agent:latestcontainer_name: beszel-agentrestart: unless-stoppednetwork_mode: hostvolumes:- ./beszel_socket:/beszel_socket- /var/run/docker.sock:/var…...

算法—选择排序—js(场景:简单实现,不关心稳定性)

选择排序原理&#xff1a;&#xff08;简单但低效&#xff09; 每次从未排序部分选择最小元素&#xff0c;放到已排序部分的末尾。 特点&#xff1a; 时间复杂度&#xff1a;O(n) 空间复杂度&#xff1a;O(1) 不稳定排序 // 选择排序 function selectionSort(arr) {for (let …...

websocket和SSE学习记录

websocket学习记录 websocket使用场景 即时聊天在线文档协同编辑实施地图位置 从开发角度来学习websocket开发 即使通信项目 通过node建立简单的后端接口,利用fs&#xff0c; path&#xff0c; express app.get(*, (req, res) > {const assetsType req.url.split(/)[…...

【统计分析120】统计分析120题分享

1-30 判断题 数学模型 指的是通过抽象、简化现实世界的某些现象&#xff0c;利用数学语言来描述他们的结构和行为&#xff0c;做出一些必要的假设&#xff0c;运用适当的数学工具&#xff0c;得到一个数学结论 数学模型&#xff1a;指的是通过抽象、简化现实世界的某些现象&am…...

【计量地理学】实验四 主成分分析与莫兰指数

一、实验内容 &#xff08;一&#xff09; 某地区35个城市2004年的7项经济统计指标数据见&#xff08;数据中的“题目1”sheet&#xff09;。 &#xff08;1&#xff09;试用最短距离聚类法对35个城市综合实力进行系统聚类分析&#xff0c;并画出聚类谱系图: 在此次实验内容…...

手写call,bind,apply

foo.Mycall(obj,1,2,3) Function.prototype.Mycallfunction(target,...args){if(typeof this!function){throw new TypeError(this is not a function)}// 判断target是否是对象if(targetnull||targetundefined){targetwindow}if(typeof target!object){targetObject(target)}/…...

【读书笔记·VLSI电路设计方法解密】问题64:什么是芯片的功耗分析

低功耗设计是一种针对VLSI芯片功耗持续攀升问题的设计策略。随着工艺尺寸微缩&#xff0c;单颗芯片可集成更多元件&#xff0c;导致功耗相应增长。更严峻的是&#xff0c;现代芯片工作频率较二十年前大幅提升&#xff0c;而功耗与频率呈正比关系。因此&#xff0c;芯片功耗突破…...

Ubuntu18.04安装Qt5.12

本文介绍了在Ubuntu18.04环境下安装QT QT5.12相关安装包下载地址 https://download.qt.io/archive/qt/5.12/ Linux系统下Qt的离线安装包以.run结尾 (sudo apt-get install open-vm-tools open-vm-tools-desktop解决无法paste的问题) 安装 1.cd命令 终端进入对应的文件夹下面 2.…...

【SpringBoot】99、SpringBoot中整合RabbitMQ实现重试功能

最近在做一个项目,需要使用 MQ 实现重试功能,在这里给各位分享一下。 1、整合 RabbitMQ <!-- rabbitmq消息队列 --> <dependency><groupId>org.springframework.boot</groupId><...

max31865典型电路

PT100读取有很多种方案&#xff0c;常用的惠斯通电桥&#xff0c;和专用IC max31865 。 电阻温度检测器(RTD)是一种阻值随温度变化的电阻。铂是最常见、精度最高的测温金属丝材料。铂RTD称为PT-RTD&#xff0c;镍、铜和其它金属亦可用来制造RTD。RTD具有较宽的测温范围&#x…...

每日一道leetcode(补充版)

1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 题目 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1,0,0,0,1…...

数据通信学习笔记之OSPF的区域

OSPFArea 用于标识一个 OSPF 的区域 区域是从逻辑上将设备划分为不同的组&#xff0c;每个组用区域号 (Area ID)来标识 OSPF 的区域 ID 是一个 32bit 的非负整数&#xff0c;按点分十进制的形式(与 IPV4 地址的格式一样)呈现&#xff0c;例如 Area0.0.0.1。 为了简便起见&#…...

5 提示词工程指南-计划与行动

5 提示词工程指南-计划与行动 计划与行动 Cline 有两种模式: Plan 描述目标和需求、提问与回答、讨论、抽象项目的各个方面、确定技术路线、确定计划 计划与确认相当于架构师,不编写代码Act 按计划编写代码 按照计划编码Plan 模式的本质是构建实际编码前的上下文,Act 的本…...

如何一键批量删除多个 Word 文档中的页眉和页脚

在工作中&#xff0c;许多 Word 文档的页眉页脚中包含公司名称、Logo、电话等信息&#xff0c;用于对外宣传。但有时我们需要批量删除这些页眉页脚信息&#xff0c;尤其当信息有误时&#xff0c;手动逐个删除会增加工作量&#xff0c;导致效率低下。本文将介绍一种便捷的方法&a…...

QCustomPlot中自定义图层

QCustomPlot 使用图层(QCPLayer)系统来组织绘图元素的绘制顺序和可见性。下面详细介绍如何自定义图层并将可绘制对象关联到特定图层。 1. 理解 QCustomPlot 的图层系统 QCustomPlot 的图层系统具有以下特点&#xff1a; 图层按顺序排列&#xff0c;后绘制的图层会覆盖前面的图…...

Dubbo QoS操作手册

QOS 操作手册 QoS概述 启动参数 参数说明默认值qos-enable是否启动Qostrueqos-port启动Qos绑定的端口22222qos-accept-foreign-ip是否运行远程访问falseqos-accept-foreign-whitelist支持的远端地址ip地址&#xff08;段&#xff09;无qos-anonymous-access-permission-lefe…...

-实用类-

1. API是什么 2.什么是枚举 &#xff01;有点类似封装&#xff01; 2.包装类 注意&#xff1a; 1.Boolean类构造方法参数为String类型时&#xff0c;若该字符串内容为true(不考虑大小写)&#xff0c;则该Boolean对象表示true&#xff0c;否则表示false 2.当包装类构造方法参…...

Apache Parquet 文件组织结构

简要概述 Apache Parquet 是一个开源、列式存储文件格式&#xff0c;最初由 Twitter 与 Cloudera 联合开发&#xff0c;旨在提供高效的压缩与编码方案以支持大规模复杂数据的快速分析与处理。Parquet 文件采用分离式元数据设计 —— 在数据写入完成后&#xff0c;再追加文件级…...