C++----类与对象(下篇)

再谈构造函数

回顾函数体内赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Date{ 
public: Date(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; 
}; 

注意:虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化, 构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值

初始化列表

格式

以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

class Date {
public: Date(int year, int month, int day): _year(year) , _month(month) , _day(day) {} private: int _year; int _month; int _day; 
};

注意

1. 每个成员变量在初始化列表中最多只能出现一次(因为初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化: 引用成员变量 、const成员变量 、自定义类型成员(且该类没有默认构造函数时)

为什么呢?

首先,当类的对象实例化时,会调用构造函数,如果有对成员变量赋值的操作,就会对成员变量进行赋值。引用成员变量、const成员变量必须在定义的时候初始化,不能再进行赋值操作,因为引用必须初始化,且当一个引用一旦引用了一个实体,就不能通过赋值操作再引用实体;而const 成员变量的值一旦被设定就不能通过赋值操作改变。

class B{ 
public: //正确写法://初始化列表:对象成员变量定义的位置,符合初始化只能初始化一次的要求。B(int a, int ref):_ref(ref),_n(10) {}//错误写法:B(int a, int ref) {//这里并不是对象成员变量定义的位置,是函数体内赋值,对成员变量赋值的地方。_ref=ref;_n=a;} private: //这里只是成员变量声明的地方,不是定义的地方。int& _ref; // 引用 const int _n; // const 
}; int main(){// 对象实例化B bb1(10, 1); B bb2(11, 2);return 0;
}

对于自定义类型成员变量_aobj,如果它有默认构造函数,那么可以不显式地在初始化列表中初始化它,编译器会自动调用默认构造函数。如果没有默认构造函数,则必须在初始化列表中显式调用其构造函数。

A 有默认构造函数:

class A {
public:A(int a = 0) : _a(a) {}private:int _a;
};class B {
public:// A 有默认构造函数,所以可以不显式初始化 _aobjB(int a, int ref) : _ref(ref), _n(10) {}private:A _aobj; // 有默认构造函数int& _ref; // 引用const int _n; // const
};

A 没有默认构造函数:

class A {
public:A(int a) : _a(a) {}private:int _a;
};class B {
public:// 在初始化列表中显式调用 A 的构造函数B(int a, int ref) : _aobj(a), _ref(ref), _n(10) {}private:A _aobj; // 无默认构造函数int& _ref; // 引用const int _n; // const
};

对于内置类型(如 int),如果初始化列表中没有显式初始化,则使用缺省值(如果有的话)或者未定义值(如果没有缺省值)。如果初始化列表中显式初始化了内置类型成员,则使用指定的值。

class B {
public:// 写法1:_x 未在初始化列表中显式初始化,使用缺省值 1B(int a, int ref) : _ref(ref), _n(10) {}// 写法2:_x 在初始化列表中显式初始化为 2B(int a, int ref, int x) : _ref(ref), _n(10), _x(2) {}private:int& _ref; // 引用const int _n; // constint _x = 1; // 缺省值为 1,但仅在未显式初始化时使用
};
3.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

我们先来看一个代码:

typedef int DataType;
class Stack {
public:Stack(size_t capacity = 10) {_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array) {perror("malloc 申请空间失败");return; }_size = 0;_capacity = capacity;}// ... 其他成员函数private:DataType* _array;size_t _size;size_t _capacity;
};class MyQueue {
public:MyQueue() {} MyQueue(int capacity) {}private:Stack _pushst;Stack _popst;
};int main()
{MyQueue q1;//这里的q1._pushst和q1._popst成员变量的capacity都是10。return 0;
}

即使在MyQueue类中的构造函数里什么操作都没有,我们也没有写初始化列表,当MyQueue类实例化对象时调用到MyQueue构造函数了,也会调用到_pushst和_popst成员变量的构造函数,因为MyQueue类中所有的成员变量还是会走初始化列表。但是如果我们显示化地写处初始化成员列表,它就会走我们写的显示化的初始化成员列表,这样我们就可以根据自己的需求设置_pushst和_popst成员变量的容量大小了(_capacity):

class MyQueue {
public:// 默认构造函数,不显式初始化_pushst和_popst,它们将使用Stack的默认构造函数(capacity为10)MyQueue() {}// 有参构造函数,使用初始化列表显式初始化_pushst和_popst的capacityMyQueue(int capacity) : _pushst(capacity), _popst(capacity) {}private:Stack _pushst; Stack _popst;  
};int main() {MyQueue q1; // 使用默认构造函数,q1._pushst和q1._popst的capacity都是10MyQueue q2(100); // 使用有参构造函数,q2._pushst和q2._popst的capacity都是100return 0;
}

4.用初始化列表动态分配空间
class Stack{
public:Stack(int capacity = 10): _a((int*)malloc(capacity * sizeof(int))),_top(0),_capacity(capacity){if (nullptr == _a){perror("malloc申请空间失败");exit(-1);}// 要求数组初始化一下memset(_a, 0, sizeof(int) * capacity);}
private:int* _a;int _top;int _capacity;
};
5.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

我们来看这样的代码:

class A { 
public: A(int a):_a1(a),_a2(_a1){} void Print() { cout<<_a1<<" "<<_a2<<endl; } private: int _a2; int _a1; 
}; int main() { A aa(1); aa.Print(); return 0;
} 

 最后它会输出什么呢?答案:1 随机值

因为它先声明的是_a2,所以初始化列表中也会先声明_a2。但此时_a1还没有被赋值(所以是随机值),所以_a2会被赋值为随机值。然后再初始化_a1,把a赋给_a1,所以_a1就是1了,所以最后会输出1 随机值。

所以建议声明的顺序和定义的顺序保持一致。

explicit关键字

我们来看这样的代码:

#include <iostream>
using namespace std;class A {
public:A(int a) : _a(a) {cout << "A(int a)" << endl;}A(const A& aa) : _a(aa._a) {cout << "A(const A& aa)" << endl;}private:int _a;
};int main() {A aa1(1);  // 直接调用构造函数 A(int a)A aa2 = 2; // 隐式类型转换:2 转换为 A 的临时对象,然后拷贝构造 aa2// 注意:以下代码会导致编译错误,因为不能从 int 直接转换为 A&// A& aa3 = 2; // error C2440: “初始化”: 无法从“int”转换为“A &”// 但是,可以转换为 const A&,因为临时对象具有常性const A& aa3 = 2; // 隐式类型转换:2 转换为 A 的临时对象,然后绑定到 const A& aa3return 0;
}

在这个例子中,A aa2 = 2; 发生了隐式类型转换,2 被用来构造一个 A 类型的临时对象,然后这个临时对象通过拷贝构造函数来初始化 aa2。然而,在同一个表达式里出现连续构造时,现代编译器通常基本都会有这样的优化。

如果我们不想要这样的隐式转换发生该怎么办呢?

在初始化列表前面加一个expilicit就可以了:

#include <iostream>
using namespace std;class A {
public:explicit A(int a) : _a(a) {cout << "A(int a)" << endl;}A(const A& aa) : _a(aa._a) {cout << "A(const A& aa)" << endl;}private:int _a;
};int main() {A aa1(1);  // 直接调用构造函数 A(int a)// 下面的代码会报错,因为 explicit 禁止了隐式类型转换// A aa2 = 2; // error C2440: “初始化”: 无法从“int”转换为“const A &”// 同样,即使绑定到 const A&,隐式类型转换也被禁止// const A& aa3 = 2; // error C2440: “初始化”: 无法从“int”转换为“const A &”// 正确的做法是显式调用构造函数A aa2(2);  // 直接调用构造函数 A(int a)const A& aa3 = A(2); // 显式创建临时对象并绑定到 const A&return 0;
}

static成员

概念

声明为 static 的类成员称为类的静态成员。用 static 修饰的成员变量称为静态成员变量;用 static 修饰的成员函数称为静态成员函数。

特性

1.静态成员也是类的成员,受public、protected、private 访问限定符的限制

2.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。

class A{
public:A(){++_scount;}A(const A& t) {++_scount;}~A(){ --_scount;}private:// 成员变量 -- 属于每个一个类对象,存储对象里面int _a1 = 1;int _a2 = 2;// 静态成员变量 -- 属于类,属于类的每个对象共享,存储在静态区,生命周期是全局的static int _scount;
};

3. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。静态成员变量不能通过缺省值初始化,因为静态成员没有初始化列表

class A{
public:A(){++_scount;}A(const A& t) {++_scount;}~A(){ --_scount;}private:// 成员变量 -- 属于每个一个类对象,存储对象里面int _a1 = 1;int _a2 = 2;// 静态成员变量 -- 属于类,属于类的每个对象共享,存储在静态区,生命周期是全局的static int _scount;// 静态成员变量不能通过缺省值初始化,因为静态成员没有初始化列表// static int _scount = 0; //错误做法
};

4. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问 ,但是要注意一些问题:

虽然可以通过对象访问静态成员,但一般不推荐这样做,因为静态成员不属于任何对象。此外,如果静态成员是私有的,则不能直接从类或对象外部访问它,需要通过公有成员函数来访问。

代码例子(错误示范)

int main() {// _scount 是私有的// 下面的代码会报错,不能突破私有权限访问静态成员变量cout << A::_scount << endl;A a;cout << a::_scount << endl;return 0;
}

正确访问方式

class A {
public:static int GetCount() {return _scount;}private:static int _scount;
};int A::_scount = 0;int main() {A a;cout << "Count: " << A::GetCount() << endl; // 正确访问cout << "Count: " << a.GetCount() << endl;  // 也可以通过对象访问,但不推荐return 0;
}

5. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员 ,但是非静态成员函数可以调用类的静态成员函数。

class A {
public:static int GetCount() {// 不能访问非静态成员// _a1++; // 错误return _scount;}void NonStaticFunc() {// 非静态成员函数可以调用静态成员函数GetCount();}private:int _a1 = 1;static int _scount;
};int A::_scount = 0;int main() {A a;a.NonStaticFunc(); // 调用非静态成员函数,内部调用静态成员函数return 0;
}

友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。 友元分为:友元函数友元类

友元函数

前面我们讲过流插入和流提取运算符的重载,就用到了友元C++----类与对象(中篇)-CSDN博客

友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
  • 友元关系是单向的,不具有交换性:比如Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
  • 友元关系不能传递:如果BA的友元,CB的友元,则不能说明CA的友元。
  • 友元关系不能继承,在继承位置再给大家详细介绍。
class Time{friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成
员变量
public:Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){}private:int _hour;int _minute;int _second;
};class Date{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}private:int _year;int _month;int _day;Time _t;
};

内部类

概念

如果一个类定义在另一个类的内部,这个内部类就叫做内部类 。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

注意

内部类就是外部类的友元类(参见友元类的定义),内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元,不可以直接访问内部类的私有属性的成员。

特性

1. 内部类可以定义在外部类的publicprotectedprivate

2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。

class A{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){cout << k << endl;//OK:直接访问外部类的静态成员变量cout << a.h << endl;//OK}};
};int A::k = 1;int main()
{A::B b;//实例化内部类B对象的写法b.foo(A());return 0;
}

3. sizeof(外部类)=外部类,和内部类没有任何关系。

class A{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){cout << k << endl;//OK:直接访问外部类的静态成员变量cout << a.h << endl;//OK}};
};int A::k = 1;int main()
{cout << sizeof(A) <<endl;return 0;
}

最终结果会输出4,我们来分析一下:

首先,需要明确的是,sizeof(A)所计算的是类A的实例在内存中所占的大小,而非类A本身作为一个类型的大小。在类A中,static int k 是一个静态成员变量。静态成员变量是属于类的,而不是类的实例的。因此,它不会占用类实例的内存空间。所有类的实例共享同一个静态成员变量的值。int h; 是一个非静态成员变量。它属于类的每个实例,并且会占用内存空间。BA的一个嵌套类,但是它没有存在外部类A中,也没有在外部类A中创建内部类的对象,所以也不会增加A的实例的大小。唯一占用空间的是h,它是一个int类型,占用4个字节。

匿名对象

概念

匿名对象是在表达式中临时创建的对象,没有名字,通常用于简化代码或直接在需要对象的地方进行一次性使用。

class A{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main(){A aa(1);  // 有名对象A(2);     // 匿名对象return 0;
}

特征

1.调用成员函数的格式

#include<iostream>
using namespace std;class Solution {
public:int Sum_Solution(int n) {cout << "Sum_Solution" << endl;//...return n;}
};int main(){Solution sl;sl.Sum_Solution(10);//有名对象调用函数的写法Solution().Sum_Solution(20);//匿名对象调用函数的写法return 0;
}

2.即用即销毁

class A{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main(){A aa(1);  // 有名对象--有名对象的生命周期在当前函数局部域A(2);     // 匿名对象--匿名对象的生命周期在所在当前行的表达式return 0;
}

3.匿名对象具有常性

#include<iostream>
using namespace std;class A{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main(){A aa(1);  // 有名对象 -- 生命周期在当前函数局部域A(2);     // 匿名对象 -- 生命周期在所在当前行的表达式//A& ra = A(1);  // 错误写法const A& ra = A(1); //正确写法:匿名对象具有常性return 0;
}

4.const引用可以延长匿名对象的生命周期

对于上一段代码,也许你会觉得,由于匿名对象的生命周期在当前行的表达式,所以ra在下一行就有变成类似于“野引用”的风险。但是const引用可以延长匿名对象的生命周期,生命周期延长至在当前函数局部域。

#include<iostream>
using namespace std;class A{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main(){A aa(1);  // 有名对象 -- 生命周期在当前函数局部域A(2);     // 匿名对象 -- 生命周期在所在当前行的表达式const A& ra = A(1); // const引用延长匿名对象的生命周期,生命周期在当前函数局部域A(10);return 0;
}

应用:C++ 编译器优化

在C++中,编译器会对临时对象的构造和拷贝进行优化,以减少不必要的开销。

以该代码为例:

#include<iostream>
using namespace std;class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};void Func1(A aa)
{}A Func2() {A aa; // 构造一个A对象return aa; // 返回值优化:一般会调用拷贝构造
}

1. 拷贝构造+拷贝构造——>一次构造(返回值优化)

当函数返回一个对象时,编译器可能会优化掉返回过程中的拷贝构造,直接构造返回的对象在目标位置。

int main() {cout << "在同一行同一个表达式时:" << endl;A ra1 = Func2(); // 拷贝构造+拷贝构造 ->优化为拷贝构造// 输出可能只显示一次构造和一次析构cout << "不在同一行同一个表达式时:" << endl;A a1;a1 = Func2();return 0;
}

输出:

2. 构造+拷贝构造——>优化为一次构造

在同一行或同一个表达式中,如果发生构造和拷贝构造,编译器可能会优化为只进行一次构造。

int main() {cout << "不会优化,因为aa1是一个已存在的对象,需要被拷贝到Func1的参数中:" << endl;A aa1;Func1(aa1);  // 但是:cout << "构造+拷贝构造 -> 优化为构造(临时对象直接构造在Func1的参数位置):" << endl;Func1(A(1));  cout << "同上,构造一个A对象时,可能会直接构造在Func1的参数位置:" << endl;Func1(1);    cout << "构造+拷贝构造 -> 优化为构造(直接构造aa2):" << endl;A aa2 = 1;  return 0;
}

输出:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重装系统后的那点事儿

每次重装系统完&#xff0c;总是有这有那的问题&#xff0c;比如这几个常见问题&#xff0c;各种C盘的数据最好在重装系统前备份哦&#xff0c;不然有点小麻烦&#xff0c;要下载好多东西&#xff01;&#xff01; 文章目录 需要新应用打开此 ms-paint新链接搜索框不见了 需要…

ROS2中通过launch读取.yaml配置文件启动节点

环境&#xff1a;Ubuntu22.04&#xff0c;ROS2-humble 通过修改.yaml配置文件中的参数&#xff0c;可以不用重新编译源代码进行软件调试。 1.yaml文件格式 bag_to_image_node&#xff1a;运行的ROS2节点名称 参数格式参考如下&#xff1a; bag_to_image_node:ros__parameters…

链原生 Web3 AI 网络 Chainbase 推出 AVS 主网, 拓展 EigenLayer AVS 场景

在 12 月 4 日&#xff0c;链原生的 Web3 AI 数据网络 Chainbase 正式启动了 Chainbase AVS 主网&#xff0c;同时发布了首批 20 个 AVS 节点运营商名单。Chainbase AVS 是 EigenLayer AVS 中首个以数据智能为应用导向的主网 AVS&#xff0c;其采用四层网络架构&#xff0c;其中…

【文档搜索引擎】搜索模块的完整实现

调用索引模块&#xff0c;来完成搜索的核心过程 主要步骤 简化版本的逻辑&#xff1a; 分词&#xff1a;针对用户输入的查询词进行分词&#xff08;用户输入的查询词&#xff0c;可能不是一个词&#xff0c;而是一句话&#xff09;触发&#xff1a;拿着每个分词结果&#xf…

MySQL 数据库优化详解【Java数据库调优】

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

ensp 关于acl的运用和讲解

ACL&#xff08;Access Control List&#xff0c;访问控制列表&#xff09;是一种常用于网络设备&#xff08;如路由器、交换机&#xff09;上的安全机制&#xff0c;用于控制数据包的流动与访问权限。ACL 可以指定哪些数据包允许进入或离开某个网络接口&#xff0c;基于不同的…

突围边缘:OpenAI开源实时嵌入式API,AI触角延伸至微观世界

当OpenAI宣布开源其名为openai-realtime-embedded-sdk的实时嵌入式API时&#xff0c;整个科技界都为之震惊。这一举动意味着&#xff0c;曾经遥不可及的强大AI能力&#xff0c;如今可以被嵌入到像ESP32这样的微型控制器中&#xff0c;真正地将AI的触角延伸到了物联网和边缘计算…

知识中台与人工智能:融合赋能企业智能化知识服务与决策

在数字化、智能化的时代背景下&#xff0c;企业面临着前所未有的机遇与挑战。为了提升知识管理与服务的能力&#xff0c;推动企业的智能化转型与发展&#xff0c;知识中台与人工智能的融合应用正成为新的趋势。知识中台作为连接数据、知识与业务的核心平台&#xff0c;能够为企…

《Web 项目开发之旅》

一、项目简介 介绍项目的背景与目标&#xff0c;说明为什么要开展这个 Web 项目。展示项目最终完成后的整体页面截图&#xff0c;让读者对项目外观有初步印象。 二、技术选型 阐述在项目中使用的前端技术&#xff08;如 HTML、CSS、JavaScript 框架等&#xff09;、后端技术…

VSCode搭建Java开发环境 2024保姆级安装教程(Java环境搭建+VSCode安装+运行测试+背景图设置)

名人说&#xff1a;一点浩然气&#xff0c;千里快哉风。—— 苏轼《水调歌头》 创作者&#xff1a;Code_流苏(CSDN) 目录 一、Java开发环境搭建二、VScode下载及安装三、VSCode配置Java环境四、运行测试五、背景图设置 很高兴你打开了这篇博客&#xff0c;更多详细的安装教程&…

【GIS教程】使用GDAL实现栅格转矢量(GeoJSON、Shapefile)- 附完整代码

文章目录 一、 应用场景1、GeoJSON2、ESRI Shapefile3、GDAL 二、基本思路1、数据准备2、重投影&#xff08;可选&#xff09;3、创建空的矢量图层4、栅格转矢量 三、完整代码四、总结五、拓展&#xff08;使用ArcGIS工具进行栅格转矢量&#xff09; 一、 应用场景 TIFF格式的…

计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

JVM系列(十三) -常用调优工具介绍

最近对 JVM 技术知识进行了重新整理&#xff0c;再次献上 JVM系列文章合集索引&#xff0c;感兴趣的小伙伴可以直接点击如下地址快速阅读。 JVM系列(一) -什么是虚拟机JVM系列(二) -类的加载过程JVM系列(三) -内存布局详解JVM系列(四) -对象的创建过程JVM系列(五) -对象的内存分…

Hive其四,Hive的数据导出,案例展示,表类型介绍

目录 一、Hive的数据导出 1&#xff09;导出数据到本地目录 2&#xff09;导出到hdfs的目录下 3&#xff09;直接将结果导出到本地文件中 二、一个案例 三、表类型 1、表类型介绍 2、内部表和外部表转换 3、两种表的区别 4、练习 一、Hive的数据导出 数据导出的分类&…

使用RKNN进行YOLOv8人体姿态估计的实战教程:yolov8-pose.onnx转yolov8-pose.rknn+推理全流程

之前文章有提到“YOLOv8的原生模型包含了后处理步骤,其中一些形状超出了RK3588的矩阵计算限制,因此需要对输出层进行一些裁剪”,通过裁剪后得到的onnx能够顺利的进行rknn转换,本文将对转rnkk过程,以及相应的后处理进行阐述。并在文末附上全部源码、数据、模型的百度云盘链…

Pytorch | 利用NI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用NI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集NI-FGSM介绍背景算法流程 NI-FGSM代码实现NI-FGSM算法实现攻击效果 代码汇总nifgsm.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对CIFAR10进行…

继承详细总结

一.继承的定义与概念 1.定义&#xff1a;继承是一种is-a的关系&#xff0c;例如&#xff0c;哺乳动物是动物&#xff0c;狗是哺乳动物&#xff0c;因此&#xff0c;狗是动物&#xff0c;等等。 2.允许我们在保持原有类特性的基础上进行扩展&#xff0c;增加方法(成员函数) 和 属…

批量多线程给TXT文档插入相关腾讯AI【高质量无水印无版权】原创图片

给蜘蛛访问的网站文章插入相关图片&#xff0c;可以带来以下好处&#xff1a; ‌1、提升用户体验‌&#xff1a;图片能够直观地展示文章内容&#xff0c;帮助用户更好地理解和消化信息。对于阅读者来说&#xff0c;图文并茂的内容往往更具吸引力&#xff0c;也能提高他们的阅读…

牵手红娘:牵手App红娘助力“牵手”,脱单精准更便捷

随着互联网的普及&#xff0c;现代青年的社交圈层加速扩大&#xff0c;他们的恋爱观也正经历着前所未有的转变。在繁忙的工作之余&#xff0c;人们希望能够找到一种既高效又真诚的交友方式。于是&#xff0c;线上交友平台成为了他们寻找爱情的新选择。让不同文化背景、不同工作…

STM32-笔记12-实现SysTick模拟多线程流水灯

1、前言 正常STM32实现多线程&#xff0c;需要移植一个操作系统FreeRTOS。但是在这里不移植FreeRTOS怎么实现多线程呢&#xff1f;使用SysTick&#xff0c;那么怎么使用SysTick来模拟多线程呢&#xff1f;前面我们知道SysTick就是一个定时器&#xff0c;它不是在主函数的while循…