【C++】类和对象(上)
文章目录
- 上文链接
- 一、类(class)
- 1. 类的定义
- 2. 类与结构体
- 3. 访问限定符
- 4. 类域
- 二、对象
- 1. 实例化
- 2. 对象大小
- 三、this 指针
- 1. 什么是 this 指针
- 2. 小练习
上文链接
【C++】入门基础知识(下)
一、类(class)
1. 类的定义
类(class)很像 C 语言中的结构体,是一个复合类型,与结构体 (C语言) 最大的不同在于类中可以定义函数。类中的内容称为类的成员,类中的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数。
class
为定义类的关键字,其后跟类的名字,类的主体用大括号{}
括起来,最后以分号;
结束。
class test // 类的名称
{int a = 0; // 成员变量void f() // 成员函数{// ...}
}; // 分号不能省略
在 C 语言中,以栈的模拟实现为例,我们可以写出类似下面的代码:
typedef struct Stack
{int* a; int top; int capacity;
}ST;void StackInit(ST* ps)
{// ...
}void StackDestroy(ST* ps)
{// ...
}void StackPush(ST* ps, int x)
{// ...
}// ...
而现在有了类,我们可以把实现栈的一系列变量和函数放在一个名为 Stack
的类中。
当我们把这些变量和函数定义在了类之中,有以下特点:
- 由于这些函数都是定义在
Stack
这个类中,所以我们在为这些函数命名的时候也就不需要写 “Stack” 这个词了,只需要根据这些函数的功能来命名即可。比如Push
、Destroy
等,更加方便。- 那如果其他类中也有
Push
或者Destroy
等操作会不会和这里的函数发生冲突呢?答案是不会。在 C++ 中作用域分四种:局部域、全局域、命名空间域以及类域。也就是说类形成了一个单独的域,而我们又知道不同的域是可以定义同名函数的,所以说不同的类中定义同名的函数不会发生冲突(关于类域后面还会提到)。- 在以前的结构体中,变量和函数是分离的。但是在类里面我们将它们放在了一起,而在同一个类之中成员函数是可以访问到成员变量的。因此我们在函数传参的时候可以不需要传入某些参数。
- 成员变量可以定义在成员函数之后,这是合法的。因为编译器会把类当作一个整体,如果编译器在某个函数中发现某个成员变量在之前没有出现过,它会在整个类中去寻找。
- 一般为了区分成员变量,一般习惯上会给成员变量加上一个特殊标识,比如在成员变量名字前面或者后面加
_
或者 以m
开头定义成员变量(m 即 member的缩写)。这一点不是 C++ 的语法要求,而是一些惯例。比如,如果变量a
是成员函数,我们一般写成_a
、a_
或者m_a
。- 定义在类中的成员函数默认为 inline,如果声明和定义分离就不是内联函数。
class Stack
{// 成员函数void Init() // 不需要写成 StackInit// 而原本的参数 ps 是用来访问数组 a 的, 现在 a 在类中可以直接访问,所以不需要传入参数{// ...}void Destroy() // 这些函数都是内联函数,因为定义在类里面{// ...}void Push(int x){// ...}// 成员变量, 定义在这里是完全没问题的int* _a; // 加上特殊标识表示这是成员变量, 也可以是 a_, m_aint _top; int _capacity;
};class Queue
{// ...void Init() // 不会和 Stack 中的 Init 函数冲突{// ...}
};
2. 类与结构体
在 C++ 中,结构体升级成了 “类”,所以在 C++ 中, struct
中也是可以定义函数的,但是一般情况下还是建议用 class
来定义类。
struct test
{int a = 0;void f() {// ...}
};
此外,在 C 语言中,若结构体没有用 typedef
的话那么 struct
+ 结构体名称才是该结构体的类型;但是类的名字就是类的类型。
但是,由于在 C++ 中结构体的升级,就算没有用 typedef
来定义结构体,也可以直接用结构体的名字作为它的类型,当然你也可以加上前面的 struct
,因为 C++ 兼容 C 语言,不过不加的话更规范。
struct Stack_1
{// ...
};class Stack_2
{// ...
};int main()
{struct Stack_1 ST; // OKStack_1 ST; // OKStack_2 ST; // OKreturn 0;
}
3. 访问限定符
当我们定义出来一个类之后,类的属性(成员变量)和方法(成员函数)也就结合到了一块儿。那么我们还可以通过一种叫访问限定符的东西来控制外部用户的访问权限,选择性地将类中的接口提供给外部的成员使用。
访问限定符有三种:private
、private
和 protected
。
用
public
修饰的成员在类外可以直接被访问。
private
和protected
修饰的成员在类外不能直接被访问,在这里暂且认为它们两个是一样的,在之后学习继承的时候才能体现出它们的区别。
一个访问限定符的修饰范围为从它开始到下一个访问限定符为止,如果后面没有访问限定符了,就到类结束。
class Stack
{
public:// 成员函数void Init() {// ...}void Destroy(){// ...}void Push(int x){// ...}
// 直到下一个访问限定符之前, 以上所有的函数均被 public 修饰, 在类外可以直接被调用。
private:// 成员变量int* _a;int _top; int _capacity;
// 如果后后面没有限定符, 那么访问限定符的修饰范围就到整个类结束。
};
我们一般都不希望外部直接访问到我们的成员变量,所以我们一般会把成员变量设置成私有的。类中的方法(函数)一般可以设置成公有,但是如果你不想让别人访问,也可以设置成私有。
如果class
中没有访问限定符修饰,都默认为 private;struct
中默认为 public。
class Stack
{void Init() // 这个函数没有被访问限定符修饰,所以默认为 private{// ...}
public:void Destroy(){// ...}private:int* _a;int _top; int _capacity;
};
4. 类域
作用域分四种:局部域、全局域、命名空间域以及类域。局部域和全局域会影响变量的生命周期,而命名空间域和类域则不会。
在之前学习命名空间的时候我们知道,编译器查找某个对象的优先顺序是先去局部域找再去全局域找,它是不会自己去命名空间域和类域中寻找的。所以如果我们在实现函数进行声明和定义分离时,必须指定类域。
// Stack.h
class stack
{
public:void Init();private:int* a;int top;int capacity;
};// Stack.cpp
#include"Stack.h"void stack::Init() // 这里必须指定类域 stack
{a = nullptr;top = 0;capacity = 0;
}
但是,有些短小的函数就不建议声明和定义分离。因为短小的函数适合作为内联函数,从而提高效率。
// Stack.h
class stack
{
public:void Init();int Top() { return a[top - 1]; }; // 直接定义在类里面, 变成内联函数private:int* a;int top;int capacity;
};
二、对象
1. 实例化
还是以栈地模拟实现为例。
// Stack.h
class stack
{
public:void Init();int Top() { return a[top - 1]; };void Destroy();void Push(int x);private:int* a;int top;int capacity;
};
// Stack.cpp
#include"Stack.h"void stack::Init()
{a = nullptr;top = 0;capacity = 0;
}void stack::Destroy()
{free(a);a = nullptr;capacity = top = 0;
}void stack::Push(int x)
{if (top == capacity){int newCapacity = capacity == 0 ? 4 : capacity * 2;int* tmp = (int*)realloc(a, sizeof(int) * newCapacity);if (tmp == nullptr){printf("realloc fail\n");exit(-1);}a = tmp;capacity = newCapacity;}a[top] = x;top++;
}
和结构体类似,当我们完整地定义好了一个类之后我们可以根据这个类来创建一个变量。只不过在 C++ 中我们一般不把这个创建出来的东西叫 “变量”,而是叫 “对象”。
// test.cpp
#include"Stack.h"int main()
{stack ST_1; // 创建出了一个 “对象”stack ST_2;// ...return 0;
}
我们在实现类的时候,仅仅只是给成员变量一个声明,并没有为它们分配空间。只有当我们使用 stack ST
创建了对象之后,才分配了空间。
而用类这种类型在物理内存中创建对象的过程,称为类实例化出对象。
类就像设计图纸一样,它规定了某个对象的设计标准是怎样的,但是它还没有去实现,没有产生实体。而实例化对象就是根据这张设计图纸去实际创造出这一个对象。类中的成员变量决定了这个对象所具有的属性,而成员函数决定了这个对象能干什么。
2. 对象大小
当我们实例化出对象之后,这个对象有多大?
类和结构体很像,在 C 语言中我们计算结构体的大小时要符合内存对齐的规则。在 C++ 中计算对象的大小时也不例外。
内存对齐的规则如下:
- 第一个成员在与结构体偏移量为 0 的地址处。
- 其他变量要对齐到某个数字(对齐数)的整数倍的地址处。
- 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
- VS 中默认的对齐数为 8。
- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体,那么嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
// Stack.h
class stack
{
public:void Init();int Top() { return a[top - 1]; };void Destroy();void Push(int x);private:int* a;int top;int capacity;
};
我们可以利用内存对齐的规则计算出上面 stack
类的成员变量的大小为 16。那么成员函数呢?
假如说现在我们创建了一个对象,那么这两个对象里面存储了它的成员变量,那它对应的成员函数的指针会不会存在这个对象里面呢?答案是不会。
为什么?我们来看下面这个例子:
#include"Stack.h"using namespace std;int main()
{stack st1;stack st2;// st1.top;st1.Init();// st2.top;st2.Init();return 0;
}
我们现在实例化出两个对象,那么这两个对象的 top
是同一个吗?不是同一个,不同的对象肯定是有各自独立的成员变量要存不同的数据的。那这里调用的两个函数 Init()
是同一个吗?是同一个。当我们设置断点查看调用函数的地址的时候会看到它们都 call 的是同一个函数的地址,即它们调用的都是同一个函数。
所以其实这些函数的指针都是一样的,存储在对象中就浪费了。如果我创建 1000 个对象,那么这个指针就重复存储了 1000 次。
需要补充的是,函数被编译后是一段指令,对象中没法储存,这些指令会存储在一个单独的区域(代码段),如果对象中非要存储的话,只能是函数的指针。
函数指针是一个地址,调用函数就是函数被编译成汇编指令然后去 call 这个地址。所以编译器在编译链接时,就要找到这个地址,不是在运行的时候找,所以这里存指针也没啥用。只有动态多态是在运行的时候找,就需要存储函数的地址,这个我们不展开。
最后,对于一个空类,或者没有成员变量的类,它所创建出来的对象的大小为 1,目的是占位,表示对象存在。
class A
{};class B
{void f(){// ...}
};int main()
{cout << sizeof(A) << endl; // 1cout << sizeof(B) << endl; // 1return 0;
}
三、this 指针
1. 什么是 this 指针
我们先来看看这段代码:
#include"Stack.h"using namespace std;class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void print(){cout << _year << '/' << _month << '/' << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2;d1.Init(2024, 9, 27);d2.Init(2025, 4, 18);d1.print();d2.print();return 0;
}
上面的代码运行结果如下:
根据上面的学习我们知道,这两个对象 d1
和 d2
调用的是同一个函数,但是它们所运行的结果却不同。为什么呢?你可能会说它们调用的函数内部的成员变量不同,那这个函数是怎么访问到这些成员变量的呢?实际上就是依靠 this 指针来实现的。
事实上,我们看起来这个 print
函数没有任何参数,但实际上在内部是有一个叫 this 的指针传入这个函数,通过这个指针来访问到我们的成员变量的,就像下面这样。
void print(Date* const this) // 关于此处的 const 下面会有解释
{cout << this->_year << '/' << this->_month << '/' << this->_day << endl;
}d1.print(&d1);
所以说调用同一个函数打印出来的东西不一样是因为编译器悄悄把该对象的地址传给 this 指针,通过 this 指针来访问到所对应的成员变量然后打印出来。
不仅仅是这个 print
函数,类中其他的函数都会隐藏一个 this 指针,比如这里的 Init
函数:
void Init(Date* const this, int year, int month, int day)
{this->_year = year;this->_month = month;this->_day = day;
}
也就是说,实际上看起来一个成员函数没有形参,实际上它有一个参数 this。看起来只有 3 个参数,实际上还有一个参数 this,只不过这个事情是编译器悄悄做的。
那要是我们写成员函数的时候把这个 this 指针写在形参上呢?不行,不能显式地传 this!但是话又说回来,虽然形参里面不能显式地去传 this,但是我们在类中可以使用 this,你不传 this 在形参中,但是你可以在函数内用 this->
访问成员变量,但是这完全没必要,因为你不写编译器也会自动加。但是有时候我们会用 this 指针来解决一些特殊的问题,必须要用,这里先不展开。
- 补充:关于指针的两个
const
int* const p
:const 在 * 的右边,修饰的是指针,表示指针本身不可变,并且这种定义下的指针必须要初始化。
const int*p
:const 在 * 的左边,修饰的是值,表示指针所指的内容不可变。所以说这里隐含的 this 指针所加的 const 意思就是 this 指针本身不能改变。
2. 小练习
- 题目一
下面程序的运行结果是( )
A. 编译报错
B. 运行崩溃
C. 正常运行
#include<iostream>using namespace std;class A
{
public:void print(){cout << "A::print()" << endl;}private:int _a;
};int main()
{A* p = nullptr;p->print();return 0;
}
我们来看看运行结果:
答案:C
为什么这段代码能正常运行?难道 p->print()
这个操作不是空指针的访问?不是的。因为这里根本就没有发生解引用操作。这里的 ->
指的意思实际上是告诉编译器我这个 print
函数是在 p 所对应的类中的一个成员函数,让编译器能找到这个函数的出处,并不是解引用去访问一个空指针。还有就是注意我们之前所讲到的一个点:成员函数的指针是没有放到对象里面的,结合这一点也可以解释这里并不是一个空指针的解引用行为。
另外一个问题是,我们类中的函数其实是会传一个 this 指针的,而这里的 this 指针就是这个 p,它是一个空指针。但是函数内部并没有对这个空指针进行解引用的操作,所以能正常运行。
p->print()
等价于A::print(p)
。
- 题目二
下面程序的运行结果是( )
A. 编译报错
B. 运行崩溃
C. 正常运行
#include<iostream>using namespace std;class A
{
public:void print(){cout << "A::print()" << endl;cout << _a << endl;}private:int _a;
};int main()
{A* p = nullptr;p->print();return 0;
}
答案:B
这道题和上面一道题是一个孪生兄弟,仅仅增加了一行代码,但是却又截然不同的效果。因为我们在上一道题中讲到说这个 print
函数实际上是传了一个 this 指针的,就是这个 p。现在这个函数中有一个成员变量 _a
,那么我们就需要通过 this 指针去访问这个成员变量。而现在这个 this 指针是一个空指针,访问 _a
的时候实际上是 this->a
,这才是属于空指针的解引用行为,所以会导致运行崩溃(注意不是编译报错,空指针的访问不是编译报错)。
- 题目三
this 指针存在内存哪个区域( )
A. 栈
B. 堆
C. 静态区
D. 常量区
E. 对象里面
首先这道题应该首先排除 E,因为之前我们就说过我们的对象只存储了成员变量,所以 this 指针肯定不会存储在对象里面。接着 C、D 选项,静态数据、全局数据存在静态区,常量数据比如字符串等存储在常量区,显然不是这两个选项,排除。对于 A、B 选项,局部数据存储在栈中, 动态开辟的数据存储在堆中。而我们的 this 指针是一个形参,而函数的参数是存在栈帧里的,因此答案选 A。
答案:A
补充:在 VS 中,由于要频繁访问 this 指针,会将 this 指针存在寄存器中。
相关文章:
【C++】类和对象(上)
文章目录 上文链接一、类(class)1. 类的定义2. 类与结构体3. 访问限定符4. 类域 二、对象1. 实例化2. 对象大小 三、this 指针1. 什么是 this 指针2. 小练习 上文链接 【C】入门基础知识(下) 一、类(class)…...
Transformer四模型回归打包(内含NRBO-Transformer-GRU、Transformer-GRU、Transformer、GRU模型)
Transformer四模型回归打包(内含NRBO-Transformer-GRU、Transformer-GRU、Transformer、GRU模型) 目录 Transformer四模型回归打包(内含NRBO-Transformer-GRU、Transformer-GRU、Transformer、GRU模型)预测效果基本介绍程序设计参…...
多级缓存入门:Caffeine、Lua、OpenResty、Canal
之前写过——Google Guava Cache简介 本文系统学习一下多级缓存 目录 0.什么是多级缓存商品查询业务案例导入1.JVM进程缓存初识Caffeine实现JVM进程缓存2.Lua语法入门HelloWorld数据类型、变量和循环函数、条件控制3.Nginx业务编码实现多级缓存安装OpenRestyOpenResty快速入门…...
在AWS Glue中实现缓慢变化维度(SCD)的三种类型
根据缓慢变化维度(SCD)的三种核心类型(类型1、类型2、类型3),以下是基于AWS Glue的实现设计、步骤及测试用例: 一、AWS Glue实现SCD的设计与步骤 1. SCD类型1(覆盖旧值) 设计目标&…...
业务校验工具包-validate-utils介绍
validate-utils介绍 1. 概述 validate-utils是一个基于Hibernate Validator的轻量级校验框架,旨在简化和增强Java应用程序中的数据校验工作。该工具包提供了一系列常见的校验场景,帮助开发人员快速实现数据验证,提高代码的可维护性和可靠性。 2. 功能特性 2.1 集合数据量…...
参数规模:衡量大语言模型体量的标尺
大语言模型的体量差异通过参数数量呈现。业界标杆如GPT-3拥有1750亿参数,Grok-1更达到3140亿级别,而Llama系列则提供70亿至700亿参数的轻量化选择。这里的"70B"并非指训练数据量,而是模型内部结构的复杂度指标——每个参数如同微型…...
JS 中call、apply 和 bind使用方法和场景
call 方法 核心特性 立即执行函数,并显式指定 this 值和逐个传递参数。语法:func.call(thisArg, arg1, arg2, …) 使用场景 借用其他对象的方法 const person { name: "Alice" }; function greet(greeting) {console.log(${greeting}, ${t…...
ZeroGrasp:零样本形状重建助力机器人抓取
25年4月来自CMU、TRI 和 丰田子公司 Woven 的论文“ZeroGrasp: Zero-Shot Shape Reconstruction Enabled Robotic Grasping”。 机器人抓取是具身系统的核心能力。许多方法直接基于部分信息输出抓取结果,而没有对场景的几何形状进行建模,导致运动效果不…...
第2讲、Tensor高级操作与自动求导详解
1. 前言 在深度学习模型中,Tensor是最基本的运算单元。本文将深入探讨PyTorch中两个核心概念: Tensor的广播机制(Broadcasting)**自动求导(Autograd)**机制 这些知识点不仅让你更加灵活地操作数据&#…...
(MySQL)表的操作
目录 表的创建 语法 创建表的案例 查看表的结构 修改表的操作 修改表名 编辑 添加一个字段(列) 修改一个字段的类型 修改字段名 删除字段名(删除列) 删除指定的表 表的插入数据 数据库的备份和恢复 我们来学习表的操作 表的创建 语法 CREATE TABLE [if not ex…...
函数的使用
函数绑定 fn.call(obj, param1, param2) fn.apply(obj, [param1, param2]) fn.bind(obj, param1, param2)()相同点: 都是借用别人(fn)的方法,替换其中的this(第一个参数)call和apply的不同点:a…...
LLM应用于自动驾驶方向相关论文整理(大模型在自动驾驶方向的相关研究)
1、《HILM-D: Towards High-Resolution Understanding in Multimodal Large Language Models for Autonomous Driving》 2023年9月发表的大模型做自动驾驶的论文,来自香港科技大学和人华为诺亚实验室(代码开源)。 论文简介: 本文…...
Spring MVC深度解析:从原理到实战
文章目录 一、Spring MVC概述1.1 MVC设计模式1.2 Spring MVC特点 二、Spring MVC核心组件2.1 架构流程图解2.2 核心组件说明 三、环境搭建与配置3.1 Maven依赖3.2 传统XML配置 vs JavaConfig 四、控制器开发实践4.1 基础控制器示例4.2 请求映射注解 五、数据处理与绑定5.1 表单…...
Spark学习全总结
基础概念: Spark 是一个快速、通用的大数据处理引擎,支持多种计算模式,如批处理、流处理、交互式查询和机器学习等。 特点: 速度快:基于内存计算,能将数据缓存在内存中,避免频繁读写磁盘,大幅…...
pytorch写张量pt文件,libtorch读张量pt文件
直接在pytorch中,用torch.save保存的张量,可能因格式差异无法在C中加载。 以下是一个最简单的例子,展示如何在 Pytorch中保存张量到 TorchScript 模块,并在 C 中使用 LibTorch 加载。 Python 代码 (save_tensor.py) import torc…...
关于Android Studio的Gradle各项配置2
好的!你提到的这些文件是 Gradle 构建系统 和 Android 项目 中非常重要的一部分,它们各自有不同的作用,涉及项目的构建配置、Gradle 环境、系统配置等方面。接下来我会为你详细解释每个文件的作用,并提供具体的例子和注释。 1. gr…...
Android Studio中创建第一个Flutter项目
一、Flutter环境验证 创建Flutter项目之前需要验证是否有Flutter环境,如没有Flutter 环境,请参考配置Flutter开发环境 1.1、flutter doctor 验证通过会有以下提示 [√] Flutter (Channel stable, 3.29.3, on Microsoft Windows [版本 10.0.19045.573…...
Linux的例行性工作(crontab)
crontab服务 at 命令是在指定的时间只能执行一次任务, crontab 命令可以循环重复的执行定时任务,与 Windows 中的计划任务有些类似 crond 是 Linux 下用来周期地执行某种任务或等待处理某些事件的一个守护进程,在安装完成操 作系统后,默认会安装 crond …...
03 基于 STM32 的温度控制系统
前言 Protues、KeilC 设计内容:使用STM32设计一个空调温度的显示控制系统 设计要求: 1.温度显示范围为16-30摄氏度 2.按键K1实现显示温度加1,按键K2实现显示温度减1,低于16或高于30,显示数值不变 3.正常按键蜂鸣器响一…...
23种设计模式-行为型模式之备忘录模式(Java版本)
Java 备忘录模式(Memento Pattern)详解 🧠 什么是备忘录模式? 备忘录模式是一种行为型设计模式,它允许在不暴露对象实现细节的情况下,保存和恢复对象的状态。备忘录模式常常用于需要记录对象状态以便随时…...
[三分钟]web自动化测试(二):selenium自动化测试常用函数(上)
文章目录 1.元素定位1.1 cssSelector(选择器)1.2 xpath1.3小示例 2.操作测试对象2.1点击/提交对象-click()2.2 模拟按键输入-sendKeys("")2.3 清除文本内容-clear()2.4 获取文本信息-getText()2.5 获取当前页面标题-getTitle()2.6获取当前页面URL-getCurrentUrl() 3.…...
基于ruoyi-plus实现AI聊天和绘画
项目介绍 基于ruoyi-plus实现AI聊天和绘画功能,打造自己的AI平台。前后端分离,有管理后台,用户端,小程序端。支持对接openai,讯飞星火,通义灵码,deepseek等大语言模型。项目架构 管理后台-前端&…...
假设检验学习总结
目录 一、假设检验1. 两种错误2. z检验和t检验3. t检验3.1 单样本t检验3.2 配对样本t检验3.3 独立样本t检验4 方差齐性检验备注卡方检验样本容量的计算AB测试主要的两种应用场景绝对量的计算公式率的计算公式说明一、假设检验 1. 两种错误 第一类错误 原假设为真,却拒绝了原假…...
C++ 基于多设计模式下的同步异步⽇志系统-2项目实现
⽇志系统框架设计 1.⽇志等级模块:对输出⽇志的等级进⾏划分,以便于控制⽇志的输出,并提供等级枚举转字符串功能。 ◦ OFF:关闭 ◦ DEBUG:调试,调试时的关键信息输出。 ◦ INFO:提⽰,普通的提⽰…...
Tauri窗口与界面管理:打造专业桌面应用体验 (入门系列五)
窗口管理是桌面应用的核心特性之一,良好的窗口管理可以显著提升用户体验。在Web开发中,我们通常被限制在浏览器窗口内,但Tauri允许前端开发者控制应用窗口的方方面面,从而创造出更加原生的体验。 窗口配置基础 初始窗口配置 在…...
golang goroutine(协程)和 channel(管道) 案例解析
文章目录 goroutine和channel概念开启线程与channel简单通信流程多个工作协程并发执行流程 goroutine和channel概念 goroutine(协程),一般我们常见的是进程,线程,进程可以理解为一个软件在运行执行的过程,线程跟协程比较类似&…...
底层源码和具体测试解析HotSpot JVM的notify唤醒有序性(5000字详解)
在大家的认知里,或者大家也可能搜过,notify唤醒机制到底是随机的呢?还是顺序的呢?在网上其实也有很多人说notify的唤醒机制就是随机的,但实际上并不是这样的,notify的唤醒机制是先进先出的! 目…...
Jenkins(CI/CD工具)
1. 什么是 Jenkins? Jenkins 是一个开源的持续集成(CI)和持续交付/部署(CD)工具,用于自动化软件构建、测试和部署过程。 2. Jenkins 优势 (1)开源免费:社区活跃&#…...
Apache Sqoop数据采集问题
Sqoop数据采集格式问题 一、Sqoop工作原理二、Sqoop命令格式三、Oracle数据采集格式问题四、Sqoop增量采集方案 Apache Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql、postgresql…)间进行数据的传递,可以将一个关系型数据库&…...
再学GPIO(二)
GPIO寄存器 每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。 GPIO…...
err: Error: Request failed with status code 400
好的,今天学习ai的时候从前端发送请求,实在是想不通为啥会啥是一个坏请求,后来从前端方法一个一个找参数,传递的值都有,然后想到我这边需要传递的是一个对象,那么后端使用的RequestParam就接收不到json对象…...
解决qnn htp 后端不支持boolean 数据类型的方法。
一、背景 1.1 问题原因 Qnn 模型在使用fp16的模型转换不支持类型是boolean的cast 算子,因为 htp 后端支持量化数据类型或者fp16,不支持boolean 类型。 ${QNN_SDK_ROOT_27}/bin/x86_64-linux-clang/qnn-model-lib-generator -c ./bge_small_fp16.cpp -b …...
k8s学习记录(五):Pod亲和性详解
一、前言 上一篇文章初步探讨了 Kubernetes 的节点亲和性,了解到它在 Pod 调度上比传统方式更灵活高效。今天我们继续讨论亲和性同时Kubernetes 的调度机制。 二、Pod亲和性 上一篇文章中我们介绍了节点亲和性,今天我们讲解一下Pod亲和性。首先我们先看…...
MongoDB与PHP7的集成与优化
MongoDB与PHP7的集成与优化 引言 随着互联网技术的飞速发展,数据库技术在现代软件开发中扮演着越来越重要的角色。MongoDB作为一种流行的NoSQL数据库,以其灵活的数据模型和强大的扩展性受到众多开发者的青睐。PHP7作为当前最流行的服务器端脚本语言之一,其性能和稳定性也得…...
maven相关概念深入介绍
1. pom.xml文件 就像Make的MakeFile、Ant的build.xml一样,Maven项目的核心是pom.xml。POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。…...
以科技之力,启智慧出行 —— 阅读《NVIDIA 自动驾驶安全报告》及观看实验室视频有感
作为中南民族大学通信工程专业的学生,近期研读《NVIDIA 自动驾驶安全报告》并观看其实验室系列视频后,我深刻感受到自动驾驶技术不仅是一场交通革命,更是一次社会生产力的解放与民族精神的升华。这场变革的浪潮中,我看到了科技如何…...
2P4M-ASEMI机器人功率器件专用2P4M
编辑:LL 2P4M-ASEMI机器人功率器件专用2P4M 型号:2P4M 品牌:ASEMI 封装:TO-126 批号:最新 引脚数量:3 封装尺寸:如图 特性:双向可控硅 工作结温:-40℃~150℃ 在…...
基础的贝叶斯神经网络(BNN)回归
下面是一个最基础的贝叶斯神经网络(BNN)回归示例,采用PyTorch实现,适合入门理解。 这个例子用BNN拟合 y x 噪声 的一维回归问题,输出均值和不确定性(方差)。 import torch import torch.nn a…...
小黑享受思考心流: 73. 矩阵置零
小黑代码 class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""items []m len(matrix)n len(matrix[0])for i in range(m):for j in range(n):if not m…...
整合 | 大模型时代:微调技术在医疗智能问答矩阵的实战应用20250427
🔎 整合 | 大模型时代:微调技术在医疗智能问答矩阵的实战应用 一、引言 在大模型技术高速变革的背景下,数据与微调技术不再是附属品,而是成为了AI能力深度重构的核心资产。 尤其在医疗行业中,微调技术改写了智能分诊和…...
Web安全:威胁解析与综合防护体系构建
Web安全:威胁解析与综合防护体系构建 Web安全是保护网站、应用程序及用户数据免受恶意攻击的核心领域。随着数字化转型加速,攻击手段日益复杂,防护需兼顾技术深度与系统性。以下从威胁分类、防护技术、最佳实践及未来趋势四个维度࿰…...
spring项目rabbitmq es项目启动命令
应该很多开发者遇到过需要启动中间件的情况,什么测试服务器挂了,服务连不上nacos了巴拉巴拉的,虽然是测试环境,但也会手忙脚乱,疯狂百度。 这里介绍一些实用方法 有各种不同的场景,一是重启,服…...
人工智能期末复习1
该笔记为2024.7出版的人工智能技术应用导论(第二版)课本部分的理论总结。 一、人工智能的产生与发展 概念:人工智能是通过计算机系统和模型模拟、延申和拓展人类智能的理论、方法、技术及应用系统的一门新的技术科学。 发展:19…...
深入理解指针(5)
字符指针变量 对下述代码进行调试 继续go,并且观察p2 弹出错误: 为什么报错呢? 因为常量字符串是不能被修改的,否则,编译器报错。 最后,打印一下: 《剑指offer》中收录了⼀道和字符串相关的笔试题&#…...
新魔百和CM311-5_CH/YST/ZG代工_GK6323V100C_2+8G蓝牙版_强刷卡刷固件包(可救砖)
新魔百和CM311-5_CH/YST/ZG代工_GK6323V100C_28G蓝牙版_强刷卡刷固件包(可救砖) 1、准备一个优盘卡刷强刷刷机,用一个usb2.0的8G以下U盘,fat32,2048块单分区格式化(强刷对ÿ…...
磁盘清理git gc
#!/bin/bash find / -type d -name “.git” 2>/dev/null | while read -r git_dir; do repo_dir ( d i r n a m e " (dirname " (dirname"git_dir") echo “Optimizing r e p o d i r " c d " repo_dir" cd " repodir"cd&…...
django admin AttributeError: ‘UserResorce‘ object has no attribute ‘ID‘
在 Django 中遇到 AttributeError: ‘UserResource’ object has no attribute ‘ID’ 这类错误通常是因为你在代码中尝试访问一个不存在的属性。在你的例子中,错误提示表明 UserResource 类中没有名为 ID 的属性。这可能是由以下几个原因造成的: 拼写错…...
现代Python打包工具链
现代Python打包工具如Poetry、Flit和Hatch提供了更简单、更强大的方式来管理项目依赖和打包流程。下面我将通过具体示例详细介绍这三种工具。 1. Poetry - 全功能依赖管理工具 Poetry是最流行的现代Python项目管理工具之一,它集依赖管理、虚拟环境管理和打包发布于一…...
(done) 吴恩达版提示词工程 8. 聊天机器人 (聊天格式设计,上下文内容,点餐机器人)
视频:https://www.bilibili.com/video/BV1Z14y1Z7LJ/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 别人的笔记:https://zhuanlan.zhihu.com/p/626966526 8. 聊天机器人(Chatbot) …...
Maven概述
1.maven是什么? Maven 是一个基于项目对象模型(Project Object Model,POM)概念的项目构建工具,主要用于 Java 项目的构建、依赖管理和项目信息管理。(跨平台的项目管理工具,用于构建和管理任何…...