C++初阶-类和对象(下)
目录
1.再探构造函数
2.类型转换
3.友元
4.static成员
5.内部类
6.匿名对象
*7.对象拷贝时的编译器优化(非必学)
8.总结
1.再探构造函数
(1)之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数初始化还有一种方式,就是初始化列表,初始化列表的使用方式是以一个冒号开始,接着是以逗号分隔的数据成员列表,每个“成员变量”后面跟一个放在括号中的初始值或表达式。
我们把这个列表放在我们自己写的构造函数的参数列表后面,加上一个:后再写成员变量(值或表达式)这样的形式,而且这个顺序是没有要求的,如:
#include<iostream>
using namespace std;
class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){}void Print()const{cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2025, 4, 21);d1.Print();return 0;
}
则结果为:
函数体内可以不写任何语句,也可以把一部分初始化放入函数体内,其次,这还可以解决:默认生成的构造对于自定义类型的成员变量只会调用它的默认构造。如之前我们写的MyQueue和Stack类:
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}
private:STDataType* _a;size_t _capacity;size_t _top;
};
// 两个Stack实现队列
class MyQueue
{
public://编译器默认⽣成MyQueue的构造函数调⽤了Stack的构造,完成了两个成员的初始化
private:Stack pushst;Stack popst;
};
我们如果开始需要开的空间不想要为4,即我们不想调用它的构造函数,我们就可以直接在MyQueue里面改为:
// 两个Stack实现队列
class MyQueue
{
public:MyQueue(int n):pushst(n), popst(n){}
private:Stack pushst;Stack popst;
};
这个适用于我想给一个显式值,不想用默认值和如果栈没有提供默认构造或者不想用栈提供的默认构造,想自己显式调用时的情况。
(2)每个成员变量在初始化列表中只能出现一次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地方。
我们如果MyQueue q(1000);是对象的整体定义,而成员变量在类中的Stack _pushst;只是声明。但我们还得找个位置给每个成员变量定义,初始化列表即每个成员变量定义的地方。有一些特殊的成员变量,必须在定义时初始化:没有默认构造的类类型变量、const成员变量、引用成员变量。必须放在初始化列表位置进行初始化,否则会编译报错。引用必须在定义时初始化(语法规定);const只有一次初始化修改它的机会就是在定义的时候,后面改不了;没有默认构造,必须传参数。因为对象整体定义对这三者无效。而初始化列表就是针对这三者的。
而其他成员变量可以在初始化列表位置初始化,也可以在函数体内初始化。
(3)建议尽量使用初始化列表初始化,因为那些你不在初始化列表初始化的成员也会走初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会用这个缺省值初始化。如果你没有给缺省值,对于没有显式在初始化列表初始化的内置成员是否初始化取决于编译器,C++并没有规定。对于没有显式在初始化列表初始化的自定义类型成员会调用这个成员类型的默认构造函数;如果没有默认构造会编译错误。
(4)C++11支持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显式在初始化列表初始化的成员使用的。
// 两个Stack实现队列
//报错的情况:
class MyQueue
{
public:MyQueue(int n, int a):pushst(n), popst(n),_size(a){}
private:Stack pushst;Stack popst;int _size;
};
//不报错的情况
class MyQueue
{
public:MyQueue(int n , int a):pushst(n), popst(n), _size(a){}
private:Stack pushst =1000 ;Stack popst = 1000 ;int _size = 0;
};
int main()
{MyQueue q;return 0;
}
实际上我们不写这个默认构造,下面这个MyQueue定义也是没有问题的
如果我们在构造函数时设置一个缺省值,那么就会根据构造函数的缺省值来进行:
class Date
{
public:Date(int year = 2025 , int month = 4, int day = 21):_year(year), _month(month), _day(day){}void Print()const{cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year = 10;int _month = 100;int _day = 1000;
};
class MyQueue
{
public:MyQueue(int a , int n = 100):pushst(n), popst(n){_size = a;}void Print()const{cout << _size << endl;}
private:Stack pushst =1000 ;Stack popst = 1000 ;int _size = 0;
};
int main()
{MyQueue q(3);q.Print();Date d;d.Print();return 0;
}
若我们不在构造函数上写缺省值,且没在初始化列表初始化并且还没有在类实例化对象时传参,我们用的就是声明时的缺省值;若写了缺省值,且在初始化列表初始化了并且还没有在类实例化对象时传参,那么就直接用的是构造函数的缺省值;否则都用的是传的实参。
如果有个数组int* _a;那我们在初始化列表时_a((int*)malloc(40))虽然空间开好了,但是我们还是需要检查这个是否真的开好了;如果真开好了,还需要把数组进行初始化。当然,我们也可以把(int*)malloc(40)作为缺省值。
三个建议:一、全部来初始化列表显式初始化;二、全部都在声明时加缺省值;三、尽量不要在构造函数和声明时缺省值混着用。
当然如果在声明时这样写:const int _i={1};是没有问题的,也可以const int _i{1};可以用{}进行初始化。
(5)初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的先后顺序无关。建议声明顺序和初始化列表顺序保持一致。
如:
class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() const{cout << _a1 << " " << _a2 << endl;}
private:int _a2 = 2;int _a1 = 2;
};
int main()
{A aa1(1);aa1.Print();return 0;
}
请问,程序运行结果是什么?
A、输出1 1
B、输出2 2
C、编译报错
D、输出1 随机值
E、输出1 2
F、输出2 1
首先我们能确定:_a1一定是1的,所以B、F排除掉;
通过我们分析发现:_a2的声明顺序比_a1先的,所以是_a2=_a1,但是此时_a1已经创建起来了,但是还没赋值,是随机值,(因为空间是在实例化对象的时候就已经开辟好空间了),所以_a2是随机值。
2.类型转换
(1)C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数;
(2)构造函数前面加explicit就不再支持隐式类型转换;
(3)类类型的对象之间也可以隐式类型转换,需要对应的构造函数支持。
如:
class A
{
public:A(int a1 ):_a1(a1){}A(int a1, int a2):_a1(a1), _a2(a2){}void Print() const{cout << _a1 << " " << _a2 << endl;}
private:int _a1 = 1;int _a2 = 2;
};
int main()
{//调用第一个A aa1(1);//调用第二个A aa2(1, 2);//类型转换A aa3 = 1;A& aa4 = 1;//会报错return 0;
}
A aa3走的是类型转换,int转换为A类型,类型转换会产生一个临时对象(调用构造函数),再用临时对象拷贝构造给了aa3。但是编译器发生了优化,会变成直接构造。
A& aa4 = 1会报错的原因是临时对象具有常性,所以可以加个cosnt在A前面 。这是单参数支持的类型转换,两个参数的(类型转换)就可以这样写:A aa5={2,2};同理,也要用引用的时候就改为:const A& aa5={2,2}这就是内置类型与自定义类型之间的类型转换。
这样有什么意义呢?
class Stack
{
public:void Push(const A& aa){}
};
int main()
{//以前Stack st1;A aa1(7);st1.Push(aa1);Stack st3;A aa3(8, 8);st3.Push(aa3);//现在Stack st2;st2.Push(7);Stack st4;st4.Push({ 8,8 });return 0;
}
假设这里的栈push(入栈)了一个aa对象,之前我们是st1和st3这种办法push的,现在我们直接用st2和st4两种方式就可以入栈了。我们如果不期望这种隐式类型转换的话,我们就可以在A的构造函数前加explicit但是它仍然支持显式类型转换。了解一下就可以了。
之前我们的内置类型也能转换,但是必须要有关联的才能转换,但是注意自定义类型之间的转换一定要借助对应的构造函数,如:
class A
{
public:A(int a1 ):_a1(a1){}A(int a1, int a2):_a1(a1), _a2(a2){}void Print() const{cout << _a1 << " " << _a2 << endl;}int Get()const{return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};
class B
{
public:B(const A& a):_b(a.Get()){}
private:int _b;
};
int main()
{A aa1(1);B bb1 = aa1;return 0;
}
如果我们不加这个构造函数,或者我们不在构造函数里面加const,这都会报错的,你可以试一下。
3.友元
(1)友元提供了一种突破类访问限定符封装的方式。友元分为:友元函数和友元类,在函数声明或者类声明的前面加friend,并且把友元声明放到一个类的里面。
如,我们之前实现的流插入和流提取中,我们如果用内置成员函数的话,那么第一个参数就是自己类类型,我们如果这样写就会发现我们需要把类类型放在>>的左边(流插入)或者<<的左边,这样不符合我们的使用习惯,而且不能连续插入和提取,则我们不能用这个作为成员函数,所以必须用其他外部。但是外部没办法访问这个成员变量,这样没办法访问,所以我们就可以这样写:
//定义Date类
class Date
{
public://友元函数friend ostream& operator<<(ostream& out,const Date& d );friend istream& operator>>(istream& in, Date d);
private://成员变量的定义int year = 1 ;int month = 1;int day = 1;
};
//<<运算符重载
ostream& operator<<(ostream& out,const Date& d)
{out << d.year << "年" << d.month << "月" << d.day << "日" /*<< endl*/;return out;
}
//>>运算符重载
istream& operator>>(istream& in, Date d)
{in >> d.year >> d.month >> d.day;return in;
}
这种方式我们就可以直接用了(这只是举个例子,没看懂之后会学的)。
(2)外部友元函数课访问类的私有和保护成员,友元函数仅仅是一种声明,它不是类的成员函数,我们也不能在函数定义时加个friend。
(3)友元函数可以在类定义的任何地方声明,不受访问限定符限制。
(4)一个函数可以是多个类的友元函数。
(5)友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有和保护成员。
如果有A、B两个类,B可能要大量访问A,每个函数都作为友元声明写入A很烦,故可以在A类中加友元声明:friend class B;直接让类成为友元类,但A不是B 的友元。也就是说A可以随意访问B中的任意成员,不受访问限定符限制,而B不可以反过来访问。
(6)友元类的关系是单向的,布局有交换性,比如:A类是B类的友元,但是B类不是A类的友元。
(7)友元关系不能传递,如果A类是B类的友元,B类是C类的友元,但是A类不是C类的友元。
(8)友元有时提供了便利。但是又元会增加耦合度,破坏了封装,所以友元不宜多用。
4.static成员
(1)用static修饰的成员变量,称之为静态成员变量,静态成员变量一定要在类外进行初始化。
(2)静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
static可以改变链接属性,只在当前文件可见,如果在.h放了个文件或变量,多个.cpp包含了以后就会出现链接错误。其次,我们计算类的大小的时候,静态成员变量不包含在这里面的,因为它在静态区。如:
class A
{
public://错误//不能在初始化列表里面初始化A(int a):_sout(a){}
private:static int _sout;//错误:static int _s = 1;
};
//也不能不初始化
int A::_sout = 0;
我们不能在类里面初始化,只能在类里面声明,但是可以在类里面使用,且初始化形式必须和我写的擦差不多!
由于静态成员变量不会受对象是否实例化影响,所以我们可以把这个对象用于计算有多少个已经实例化的对象,在构造函数里面加一个++_sout,如果我们还想测到底还有多少个没销毁的对象,我们可以在析构函数里面加:--_sout这种方式。
(3)用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针。
因为没有this指针,所以不能访问成员变量,因为每个成员变量前都有this->。我们可以用静态成员函数来返回静态成员变量,只能访问静态成员变量。
(4)静态成员函数可以访问其他的静态成员,但是不能访问非静态的,因为没有this指针。
非静态的成员函数也不可以访问!反之就可以!
(5)非静态的成员函数,可以访问任意的静态成员变量和静态成员函数。
(6)突破类域就可以访问静态成员,可以通过类名::静态成员或者对象.静态成员来访问静态成员变量和静态成员函数。
(7)静态成员也是类的成员,受访问限定符的限制。
(8)静态成员变量不能再声明位置给缺省值初始化,因为缺省值是给构造函数初始化列表的,静态成员变量不属于某一个对象,不走构造函数初始化列表。
题目:
已经有ABCD四个类的定义,程序中A,B,C,D构造函数调用的顺序是:()?
class A
{
};
class B
{
};
class D
{
};
//类的声明
C c;
int main()
{A a;B b;static D d;return 0;
}
class C
{
};
由于C是全局变量,所以肯定先构造C,D是静态变量,由于其声明周期是全局的,但它不是在main函数之前就初始化的,而是在运行到这个地方才会调用构造,所以顺序是:CABD
如果是析构函数调用顺序呢?
有个特点:后定义的先析构,但是这是在局部里面起作用,所以是B A,其次局部静态的先析构,再全局析构,所以析构的顺序是:BADC
5.内部类
(1)如果一个类定义在另一个类的内部,这个就叫内部类。它是一个独立的类,跟定义再全局相比,它知识收到外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
class A
{
//public:class B{public:void foo(const A& a){cout << _k << a._h << endl;}int _b1 = 1;int _b2 = 1;};
//private:static int _k;int _h = 1;
};
int A::_k = 1;
int main()
{cout << sizeof(A) << endl;return 0;
}
结果为:
这也说明了A里面没有B对象,证明内部类并不是在A里面,只是定义在A里面,受类域和访问限定符的限制而已。只是访问时需要A:: B b;指定A这个类域才能实例化出对象,如果是私有的,则外部是访问不了的。
(2)内部类默认是外部类的友元。
B可以用A里面的元素,但是A不可以用B里面的私有部分,A不是B的友元。
(3)内部类本质也是一种封装。
如A类实现出来就是给B类使用,那么可以把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。
这个只要了解一下即可。
6.匿名对象
用类型(实参)定义出来的对象叫做匿名对象,相比之前我们定义的类型 对象名(实参)定义出来叫有名对象。匿名对象的生命周期只在这一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象。
如,A是一个类,我们写出的A aa1;A aa2(2);这种方式是有名对象,而我们若这样写A(1);A(2);则是匿名对象。其中匿名对象生命周期只有这一行,在下一行就会调用析构函数。
临时对象时编译器自己产生的,匿名对象时我们自己创建的。
如果想要延长匿名对象的生命周期,可以:const A& ref = A();加const是因为临时对象具有常性。匿名对象跟着引用走,也就是说ref销毁,匿名对象才会销毁。这个匿名对象是开了空间的,所以能用引用!
这个东西的用法就是:
(1)我们之前打印类的一句话,之前是要实例化一个对象再调用函数的如:A a;a.Print();而现在是A().Print();注意:这里的()不能去掉,如果去掉就相当于实例化对象了,而我们也不能A a()这样写,因为会编译报错,不知道是实例化对象还是调用函数。
(2)我们若在一个函数中形参为自定义类型,但我们想给缺省值,可以:
void func2(A aa=A()){}给匿名对象作为缺省参数,但传值一般用引用,所以我们可以改为:
void func2(const A& aa=A())
匿名对象之后还会用到的,所以这里就简单介绍一下用法就可以了!
下一节是了解内容,深层太难理解了,所以了解一下就可以了,不看也没什么事!
*7.对象拷贝时的编译器优化(非必学)
(1)现代编译器为了尽可能提高程序效率,在不影响正确性的情况下会尽可能减少一些传参和传返回值的过程中可以省略的拷贝。
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;
};
(1)如果A aa1=1;这句话就是类型转换,编译器会优化成直接构造(优化之前是构造加拷贝构造)。
而直接构造就相当于A aa1(1);虽然二者结果一样,但是过程不一样,我们可以把它写到主函数里面,则会打印出这个结果:
这是一个优化后的结果,发现是直接构造加析构。
如果想要看没有优化的结果,则需要到Linux在编译时加上g++ test.cpp -fno-elide-const ructors的方式关闭构造相关的优化。
(2)若void f1(A aa){} A aa1(1);f1(aa1);
这样是不会优化的,因为对象开始已经创建出来了,后面构造加拷贝构造(aa1对象)。但是如果
f1(1);f1(A(1));
f1(1)有类型转换,产生临时对象再构造,拷贝构造,被优化,A(1)按语法步骤先构造再拷贝构造,会被优化成直接构造,代码如下:
void f1(A aa)
{
}
int main()
{f1(1);f1(A(1));return 0;
}
结果为:
若关闭优化,则在A(int a);后加了一个A(const A& aa);,并且析构函数还多调用了一次:
(3)隐式类型转换中都尝试优化,其次还有传值返回,不优化的情况下传值返回,编译器会生成一个拷贝返回对象的临时对象作为函数调用表达式的返回值,一些编译器会优化得更厉害,将构造的局部对象的拷贝构造的临时对象优化成直接构造。
A f2()
{A aa;return aa;
}
int main()
{A aa2 = f2();return 0;
}
在返回时会产生临时对象,如果再用aa2来接收返回值,那么就又有拷贝构造,所以为:构造+2个拷贝构造,但编译器会优化成1个拷贝构造+构造;而在VS2022上就会直接优化成直接构造。
其逻辑可以见下面图:
在VS2019的debug版本就会优化一些过程,而在VS2019的release版本和VS2022上直接优化成构造了。但是如果A aa2;aa2=f2();这是赋值,会干扰编译器的优化的。但是release版本不产生临时对象的,所以结果会为:
而在VS2022则会进行优化:
不论怎么样,都要额外调用这个赋值运算符重载的函数,所以不建议这样写!
这个知识点理解起来难度比较高,主要是了解以后之后建议哪样写。
8.总结
类和对象下难度还是相对高的,知识点也是有些需要了解,有些也是需要记住的,但是只要去深究那么这种东西也会很简单的。下节将讲解:C/C++内存管理,喜欢的可以一键三连哦!
相关文章:
C++初阶-类和对象(下)
目录 1.再探构造函数 2.类型转换 3.友元 4.static成员 5.内部类 6.匿名对象 *7.对象拷贝时的编译器优化(非必学) 8.总结 1.再探构造函数 (1)之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值&#…...
RPC通信原理实战
RPC概念及RPC请求响应流程 RPC概念引入 假设有两个模块,用户和订单 在单体项目中,两个模块被打包到一个包,都处在一个tomcat进程中,用户模块调用订单模块属于同一进程内的本地调用 在微服务项目中,用户模块和订单模…...
自动创建 中国古代故事人物一致性图画,看看扣子的空间是否能达到你的满意,自媒体的福音?
欢迎来到涛涛聊AI 看效果: AI绘画最难的人物一致性问题,每次得到的结果都不一致。 官方介绍: 扣子空间是你和 AI Agent 协同办公的最佳场所。 在扣子空间里,精通各项技能的「通用实习生」,各行各业的「领域专家」&…...
【Unity笔记】Unity音效管理:ScriptableObject配置 + 音量控制 + 编辑器预览播放自动化实现
摘要: 本文介绍了如何在 Unity 中构建一个高效的音效管理系统,通过 ScriptableObject 实现音效集中配置,支持为每个音效单独设置音量,并通过自定义 Editor 实现音效的可视化预览播放与下拉选择播放功能,整个系统无场景…...
面向高可靠场景的RISC-V低功耗MCU硬件安全设计
该RISC-V架构的低功耗MCU通过多项硬件级安全技术满足工业控制、汽车电子及物联网等领域对可靠性与安全性的需求。其核心特性包含六个方面: 在数据完整性验证与固件安全升级方面,该MCU通过硬件级校验机制(如CRC、哈希算法)确保固件…...
OpenVINO教程(五):实现YOLOv11+OpenVINO实时视频目标检测
目录 实现讲解效果展示完整代码 本文作为上篇博客的延续,在之前实现了图片推理的基础上,进一步介绍如何进行视频推理。 实现讲解 首先,我们需要对之前的 predict_and_show_image 函数进行拆分,将图像显示与推理器(pre…...
【新能源科学与技术】MATALB/Simulink小白教程(一)实验文档【新能源电力转换与控制仿真】
DP读书:新能源科学与工程——专业课「新能源发电系统」 2025a 版本 MATLAB下面进入正题 仿真一:Buck 电路一、仿真目的二、仿真内容(一)Buck电路基本构成及工作原理(二)Buck电路仿真模型及元件连接…...
软件项目实施全流程及交付物清单
需求分析 -> 概要设计 -> 详细设计 -> 开发 -> 测试 -> 部署 -> 上线运行 一、确认项目目标、范围和团队成员 二、收集和分析客户需求,确定需求规格 三、制定详细的项目计划,包括时间表、资源计划、预算 四、系统架构设计…...
Docker安装ES :确保 Kibana 正确连接 Elasticsearch
在使用 Docker 部署 ELK(Elasticsearch、Logstash、Kibana)堆栈时,正确的服务配置和依赖管理至关重要。本文将分享如何优化 Docker Compose 配置,确保 Kibana 能稳定连接到 Elasticsearch,并提供故障排查建议 cd /opt/…...
云贝餐饮 最新 V3 独立连锁版 全开源 多端源码 VUE 可二开
云贝餐饮源码 最新 V3 独立连锁版 全开源 多端源码 VUE 可二开 vue uniapp 独家优化版本 后台管理 Vue 源文件 后台管理文件 yii2 升级包 (全开源) 收银台 Vue 源文件 装修 Vue 源文件 商家端 uni-app 源文件 用户端 uni-app 源文件 数据库文件 云贝餐饮…...
python异步协程async调用过程图解
1.背景: 项目中有用到协程,但是对于协程,线程,进程的区别还不是特别了解,所以用图示的方式画了出来,用于理清三者的概念。 2.概念理解: 2.1协程,线程,进程包含关系 一…...
【Java学习笔记】选择结构
选择结构 内容结构 一、顺序结构 二、分支控制 (1)单分支 (2)双分支 (3)多分支 (4)嵌套分支 (5)switch 分支结构 三、switch和if的比较 一、顺序结构…...
java Nacos
windows下载nacos,版本2.x的,1.0的话会出现“Server check fail, please check server 127.0.0.1 ,port 9848 is available , error {}” 这个鬼问题 下载链接 这里用的是2.0.4版本,启动的话用 startup.cmd -m standalone,单体启…...
c语言之杂识
前言 主要说一下c语言的杂知识 一、预处理指令 1. #include #include指令用于包含其他头文件的内容到当前文件中。这允许您在程序中使用其他模块定义的函数和变量。 示例: #include <stdio.h> // 包含标准输入输出头文件int main() {printf("Hello…...
CSS内边距、外边距、边框
CSS内边距 内边距 :内容区(Content)与边框(Border)之间的透明间距,用于增加元素内部的留白。不影响元素内容本身的尺寸(如文字大小),但会增大元素的总占用空间。 以下是…...
融山科技前端面经
前端面试问题解答 这次是波珠的第三次面试,持续打怪升级,积累面试中面试官问到的不会的点子。 1.自我介绍 面试官您好,我是来自XX学校XX专业本科的XX名字,然后介绍在学校情况,我就介绍了大一自学前端,然…...
元素滚动和内容垂直居中同时存在,完美的 html 元素垂直居中的方法flex + margin: auto
假设有一个元素 div 作为父容器且宽高固定,里面的内容 content 在父容器中垂直/水平都居中,且当内容很多时,父元素滚动overflow: auto,content的内容要能够完全展示。 我之前在这篇文档提到了两个方法: 使用 flex s…...
STM32F103 单片机(基于 ARM Cortex-M3 内核)的启动过程涉及硬件初始化、固件配置和程序执行流程。
1. 启动模式与地址映射 STM32F103 的启动模式由 BOOT0 和 BOOT1 引脚配置决定,不同的启动模式对应不同的存储器映射: 启动模式 映射地址范围 说明 主 Flash 0x08000000~0x0807FFFF 用户程序存储在 Flash 中,复位后从 Flash 启动(…...
c++中iota容器和fill的区别
在C 中,std::iota 和 std::fill 都是标准库中的函数,用于对序列进行操作,它们的功能和用法如下: std::iota 功能:std::iota 函数用于将一个连续的递增序列赋值给指定范围的元素。它接受三个参数,第一个参…...
Kafka集群
kafka集群: kafka-server-start.sh;kafka-server-stop.sh cd/opt/software/kafka/ kafka.sh上传:cd /usr/local/bin/ 执行文件变成绿色:chmod 777 kafka.sh Kafka.sh start Xcall.sh jps...
多源数据集成技术分析与应用实践探索
摘要:本文聚焦多源数据集成技术,深入剖析联邦式、基于中间件模型及数据仓库三类主流技术的侧重点与应用场景。通过实际案例阐述多源数据集成应用构建过程,旨在为企业数据整合与共享提供理论指导与实践参考,助力企业提升数据利用效…...
UniOcc:自动驾驶占用预测和预报的统一基准
25年3月来自 UC Riverside、U Wisconsin 和 TAMU 的论文"UniOcc: A Unified Benchmark for Occupancy Forecasting and Prediction in Autonomous Driving"。 UniOcc 是一个全面统一的占用预测基准(即基于历史信息预测未来占用)和基于摄像头图…...
反向代理和DDNS的区别是什么?
反向代理(Reverse Proxy)和动态域名解析(DDNS,Dynamic Domain Name System)是两种不同的网络技术,虽然它们都与外部访问内部服务相关,但解决的问题和应用场景完全不同。具体区别如下:…...
markdown展示数学公式
要让Markdown正确展示数学公式,你需要使用支持数学公式渲染的工具,比如在支持LaTeX语法的Markdown编辑器中进行编写。 Markdown本身并不原生支持数学公式的渲染,但许多Markdown解析器(例如在GitHub、Jupyter Notebooks、或一些博…...
服务器编译环境配置及数据接收脚本编写(11)
文章目录 一、本章说明二、云端服务器Python编译环境配置三、传感数据解析脚本编写一、本章说明 注:本节为【基于STM的环境监测系统(节点+云服务器存储+QT界面设计)】项目第11篇文章,上面两篇介绍了云服务器数据库的安装与相关设置,本章主要介绍在服务器中安装Python编译…...
硬件基本概念
目录 基本概念 电压 电流 串联、并联 欧姆定律 电路仿真网址: 功率 焦耳定律 AC220V 转 DC5V 基本电子元器件了解 电阻:(电阻器) 电容 电感 继电器 二极管 三极管 晶振(晶体振荡器) 光耦…...
Spark与Hadoop之间的联系与区别
联系 生态系统互补: Hadoop 是一个分布式存储和计算平台,主要包括 HDFS(分布式文件系统)和 MapReduce(分布式计算框架)。Hadoop 提供了可靠的数据存储和分布式计算的基础。 Spark 是一个高性能的分布式计算…...
spark和Hadoop之间的对比与联系
对比 计算模型: Hadoop:采用MapReduce计算模型,分map与reduce两个阶段,数据处理按阶段顺序执行,数据处理按阶段顺序执行,中间结果会写入磁盘,I/O开销大。 Spark:基于弹性分布式数…...
0802api设计和实战-网络ajax请求1-react-仿低代码平台项目
文章目录 1 API设计1.1 用户功能1.1.1 获取用户信息1.1.2 注册1.1.3 登录 1.2 问卷功能1.2.1 获取单个问卷1.2.2 获取问卷列表1.2.3 创建问卷1.2.4 更新问卷1.2.5 批量彻底删除问卷1.2.6 复制问卷 1.3 小结 2 实战2.1配置axios2.2 封装API和测试2.3 新建问卷2.4 自定义hooks封装…...
什么是CAN的非破坏仲裁?
CAN总线的非破坏性仲裁是一种在多个设备同时发送数据时,通过标识符(ID)优先级来决定哪个设备可以优先发送数据的机制。其核心思想是:当多个设备同时发送数据时,ID值较小的数据具有更高的优先级,能够优先…...
无线监控系统分类全解析:搭配视频融合平台EasyCVR开启高效监控
随着技术的发展,无线监控系统在家庭、小型企业、特定行业以及室外恶劣环境中的应用越来越广泛。本文将介绍几种常见的无线监控系统,分析其优缺点,并结合EasyCVR视频融合平台的功能,探讨如何优化无线监控系统的性能和应用。 一、主…...
并行RANSAC平面拟合(C++)
依赖库 1)Eigen 2)GLM 算法大致思路 Step 1:源点云随机采样3个点; Step 2:3个点拟合平面,统计符合该平面模型的点,为inlier点; Step 3:判断inlier点比例是否达到阈…...
Docker核心技术精讲:从入门到企业级实战
第一章>Docker概述 第二章>Docker安装与镜像下载加速 第三章>镜像 第四章>容器 第五章>发布镜像到阿里云或私有化仓库 第六章>容器卷 第七章>Docker安装常用软件 第八章>Docker高级版-Mysql主从复制、Redis主从、分布式存储 第九章>Doc…...
【KWDB 创作者计划】_深度学习篇---向量指令集
文章目录 前言一、加速原理数据级并行(DLP)计算密度提升减少指令开销内存带宽优化隐藏内存延迟 二、关键实现技术1. 手动向量化(Intrinsics)优势挑战 2. 编译器自动向量化限制 3. BLAS/LAPACK库优化4. 框架级优化 三、典型应用场景…...
音视频小白系统入门课-4
本系列笔记为博主学习李超老师课程的课堂笔记,仅供参阅 往期课程笔记传送门: 音视频小白系统入门笔记-0音视频小白系统入门笔记-1音视频小白系统入门笔记-2音视频小白系统入门笔记-3 将mp4文件转换为yuv文件 ffmpeg -i demo.mp4 # 输入文件-an …...
CS144 Lab3 实战记录:TCP 发送器实现
文章目录 1 实验背景与目标2 TCP发送器的实现2.1 整体流程2.2 核心组件2.3 窗口管理2.4 关键函数实现2.4.1 push函数2.4.2 receive函数2.4.3 tick函数 3 仓库地址 1 实验背景与目标 在 TCP 协议中,发送器(TCP Sender)是实现可靠传输的核心组…...
Transformer:引领深度学习新时代的架构
引言 在深度学习的快速发展历程中,Transformer 架构如同璀璨的新星,照亮了自然语言处理(NLP)以及计算机视觉(CV)等众多领域的前行道路。自 2017 年在论文《Attention Is All You Need》中被提出以来&#…...
基于RabbitMQ实现订单超时自动处理
基于RabbitMQ实现订单超时自动处理 引言 在现代电商系统中,订单超时自动取消是一个常见的业务需求。传统的定时任务扫描数据库的方式存在性能瓶颈和实时性差的问题。本文将介绍如何使用RabbitMQ的消息队列和死信队列特性,构建一个高效可靠的订单超时自…...
nginx实现同一个端口监听多个服务
nginx实现同一个端口监听多个服务 前言原理配置不同域名基于路径(URL 路由)补充 总之完结撒花,如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论! 前言 受同…...
用 Firebase 和 WebRTC 快速搭建一款浏览器视频聊天应用
在现代 Web 应用中,实时音视频通信变得越来越普遍。本文将通过一个简洁实用的示例,带你一步步搭建一个基于 Firebase WebRTC 的浏览器视频聊天应用,帮助你理解 WebRTC 的核心通信机制以及如何借助 Firebase 进行信令传输。 🔧 技…...
记录一次OGG进程abended,报错OGG-01431、OGG-01003、OGG-01151、OGG-01296问题的处理
1. ogg进程abended的几种常见原因: 1. undo表空间不足导致abended。 2. 数据不一致,违反唯一约束导致abended。 3. 源端和目标端表结构不一致导致abended。 4. 源端表名过长,同步到目标端报错导致abended。 5. OGG-03517字符集转换问题导…...
机器学习分类算法详解:原理、应用场景与测试用例
机器学习分类算法详解:原理、应用场景与测试用例 一、基础分类算法 1. 决策树 原理: 通过递归划分数据集,选择信息增益(ID3)或基尼系数(CART)最大的特征作为分裂节点,构建树结构。叶节点代表分类结果。应用场景: 医疗诊断(需解释性,如判断疾病风险)。客户分群(如根…...
机器人仿真:相机信息仿真及显示
1)概要 除了激光雷达以外,机器人常用的视觉传感器还包括相机,相机图像能够获取真实世界的真实颜色和纹理信息,能够被用于进行目标检测、分割和追踪。 2)结果展示...
车载功能测试-车载域控/BCM控制器测试用例开发流程【用例导出方法+优先级划分原则】
目录 1 摘要2 位置灯手动控制简述2.1 位置灯手动控制需求简述2.2 位置灯手动控制逻辑交互图 3 用例导出方法以及优先级原则3.1 用例导出方法3.1.1 用例导出方法介绍3.1.2 用例导出方法关键差异分析 3.2 优先级规则3.2.1 优先级划分的核心原则3.2.2 具体等级定义与判定标准 3.3 …...
gem5-gpu教程05 内存建模
memory-modeling|Details on how memory is modeled in gem5-gpu ====== gem5-gpu’s Memory Simulation ====== gem5-gpu, for the most part, eschews GPGPU-Sim’s separate functional simulation and instead uses gem5’s execute-in-execute model. Therefore, memory …...
如何提升个人解决问题的能力?
提升个人解决问题的能力是一个系统性工程,涉及思维、知识、经验和心态的多方面提升。以下是一些具体且可操作的方法,帮助你逐步增强解决问题的能力: 1. 培养「结构化思维」 明确问题本质: 遇到问题时,先问自己&…...
CSS清楚默认样式
* {margin: 0;padding: 0;box-sizing: border-box;} 这段 CSS 代码是一个常见的全局样式重置代码块,它会对网页中的所有元素(通过通配符 * 选择器)应用相同的样式规则,下面分别解释每一条规则的作用。 margin: 0; 在 HTML 中&a…...
问题:raw.githubusercontent无法访问
问题:raw.githubusercontent无法访问 文章目录 一、问题二、hosts文件2.1、hosts文件简介2.2、hosts文件位置2.3、hosts文件修改 3、解决方法3.1、查询出raw.githubusercontent.com的ip地址3.2、在/etc/hosts里填写IP地址3.3、再次执行命令 4、一些常用IP地址 一、问…...
【C语言】文本操作函数fgetc、fputc、fgets、fputs、fprintf、fscanf、fread、fwrite
一、介绍 二、简要概括 三、函数的使用 1、fgetc和fputc int fgetc ( FILE * stream ); 从文件中读取信息,每次读取一个字符 从流中获取字符返回指定流的内部文件位置指示符当前指向的字符。然后将内部文件位置指示符推进到下一个字符 int main() {//打开文件FI…...
(19)VTK C++开发示例 --- 分隔文本读取器
文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容👉内容导航 👈👉VTK开发 👈 1. 概述 本例采用坐标和法线(x y z nx ny nz)的纯文本文件,并将它们读入vtkPolyData并显示…...