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

c++面试题

1.static的使用

1)修饰局部变量:在函数内部使用static修饰局部变量,会使它成为静态局部变量。静态局部变量只会被初始化一次,且只有在第一次调用该函数时才会被初始化,之后每次调用该函数时都会保留上一次的值.从原来的栈区存放改为全局区。

2)修饰全局变量:在函数外部使用static修饰全局变量,会使它成为静态全局变量。静态全局变量的作用域仅限于当前文件,即只能在当前文件内被访问,不能被其他文件访问。

3)修饰成员变量:在类中使用static修饰成员变量,会使它成为静态成员变量。静态成员变量的生命周期与程序的生命周期相同,即它只会被初始化一次,且存在于所有类对象之外。静态成员变量在类内部声明,在类外部需要进行定义和初始化。

4)修饰成员函数:在类中使用static修饰成员函数,会使它成为静态成员函数。静态成员函数不依赖于任何类对象,只能访问类的静态成员变量和静态成员函数,不能访问类的非静态成员变量和非静态成员函数。静态成员函数通过类名来访问。

2.const的使用

1)修饰变量:变量的值不能改变

2)修饰指针:左定值(常量指针)右定向(指针常量)

3)修饰成员变量:const修饰成员变量,只在某个对象的生命周期中是常量,因为类可以创建多个对象,不同的对象其const数据成员值可以不同。所以不能在类的声明中初始化const数据成员,因为类的对象还没有创建时,编译器还不知道const数据成员值是多少。所以只能在类的构造函数的初始化列表中初始化。

4)修饰成员函数:可以使用类中的所有成员变量,但是不能改变他们的值。

3.指针常量,常量指针,常指针常量

1)指针常量:可以改变指针指向的值,但是不能改变指针的指向

2)常量指针:可以改变指针的指向,但是不能改变指针指向的值

3)常指针常量:指针的指向和指向的值都不能改变

4.指针和引用的异同

相同点:都可以对变量进行改变

不同点:

1)指针本质是一个变量,需要分配内存,引用是给一个对象起别名,不需要分配内存

2)引用在定义时必须初始化,而指针可以不用初始化

3)指针初始化可以为空,但是引用必须是一个已有对象的引用

4)指针和引用的自增运算结果不同。指针是指向下一个地址,而引用是引用的变量值+1

5)Sizeof不同,指针得到的是指针的大小,引用得到的是引用变量的大小。

5.如何理解多态

定义:同一操作作用于不同的对象,产生不同的执行结果。C++多态意味着当调用虚成员函数时,会根据调用类型对象的实际类型执行不同的操作。

在日常生活中的多态例子:买票时,成人买票全价,如果是学生那么半价,如果是军人,就可以优先买票。不同的人买票会有不同的实现方法,这就是多态。

C++的多态必须满足两个条件:
1 必须通过基类的指针或者引用调用虚函数
2 被调用的函数是虚函数,且必须完成对基类虚函数的重写

实现:通过虚函数实现,用virtual声明的成员函数就是虚函数,允许子类重写。声明基类的指针或者引用指向不同的子类对象,调用相应的虚函数,可以根据指针或引用指向的子类的不同从而执行不同的操作。

        Overload(重载):函数名相同,参数类型或顺序不同的函数构成重载。

        Override(重写):派生类覆盖基类用virtual声明的成员函数。

        Overwrite(隐藏):派生类的函数屏蔽了与其同名的基类函数。派生类的函数与基类函数同名,但是参数不同,隐藏基类函数。如果参数相同,但是基类没有virtual关键字,基类函数将被隐藏。

6.虚函数表

       1)带有虚函数的类,编译器会为其分配一个虚函数表(用数组实现),里面记录了虚函数的地址,当此类被继承时,若子类重写了虚函数,则在子类的虚函数表中覆盖父类的虚函数地址,否则继承父类的虚函数地址。

        2)实例化后,对象有一个虚函数指针,虚函数指针指向虚函数表,在程序运行时,通过虚函数指针找到虚函数表中对应的函数地址,调用虚函数

7.常用数据结构

vector:向量,连续存储,可随机访问。
deque:双向队列,连续存储,随机访问。
list:链表,内存不连续,不支持随机访问。
stack:栈,不可随机访问,只允许再开头增加/删除元素。
queue:单向队列,尾部增加,开头删除。不支持随机访问
set:集合,采用红黑树实现,可随机访问。查找、插入、删除时间复杂度为O(logn)。
map:图,采用红黑树实现,可随机访问。查找、插入、删除时间复杂度为O(logn)。
hash_set:哈希表,随机访问。查找、插入、删除时间复杂读为O(1)。

8.TCP

9.C和C++的区别

C语言是面向过程的,C++是C的超集,继承并扩展了C语言,是面向对象的

10. struct 和class 有什么区别?

1)struct的成员默认是public属性的,class的成员默认是private属性的

2)struct继承默认是public属性的,class继承默认是private属性的

3)“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数

11.extern "C"的作用

extern "C" 的主要作用就是为了能够正确实现C++代码调用其它C语言代码。加上extern "C"后,会提示编译器这部分代码按C语言(而不是C++)的方式进行编译。

12.C++重载、重写、多态

重载:位于同一个类中,函数名字相同,形参列表不同

重写:被重写的函数必须是virtual,一般用于子类在继承父类是,重写父类中的方法,函数名称和参数列表都相同

多态:要有继承,要有虚函数重写,父类指针或引用指向子类对象。

13.多态的理解

多态:就是多种形态,C++的多态分为静态多态和动态多态。静态多态就是重载,因为在编译器决议确定,所以成为静态多态。动态多态即运行时多态是通过继承重写基类的虚函数实现的多态,因为在运行时决议确定,所以称为动态多态,也叫运行时多态。

14.对虚函数机制的理解,单继承、多继承、虚继承条件下虚函数表的结构

单继承:一个子类只有一个直接父类时称这个继承关系为单继承。将基类虚表中的内容拷贝一份到子类虚表中,如果派生类重写了基类某个虚函数,就用派生类自己的虚函数替换掉原先基类虚函数的入口地址。

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承。多重继承会有多个虚函数表,几重继承就会有几个虚函数表。这些表按照派生的顺序一次排列,如果子类改写了父类的虚函数,那么就会用子类自己的虚函数覆盖虚函数表相应的位置,如果子类有新的虚函数,那么就添加到第一个虚函数表的末尾。

虚继承:C++使用虚拟继承,解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。

15.如果虚函数是有效的,那为什么不把所有函数设为虚函数?

虚函数是有代价的,由于每个虚函数的对象都要维护一个虚函数表,因此在使用虚函数的时候会产生一定的系统开销,这是没有必要的。另外,虚函数的调用相对于普通函数要更慢一些,因为每次都要查找虚函数表,有一定的时间开销。

16.为什么要虚继承?

非虚继承时,显然D会继承两次A ,内部就会存储两份A的数据,浪费空间,而且还会有二义性,D调用A的方法时,由于有两个A,究竟调用哪个A的方法呢,编译器也不知道,就会报错,所以有了虚继承,解决了空间浪费以及二义性问题。在虚继承下,只有一个共享的基类对象被继承,而无论该基类在派生层次中出现多少次。共享的基类子对象被称为虚基类,在虚继承下,基类对象的复制以及由此引起的二义性被消除了。

17.构造函数为什么一般不定义为虚函数、析构函数一般定义为虚函数

1.构造函数不可以定义为虚函数:虚函数的调用需要通过虚函数指针指向虚函数表,虽然虚函数表在编译时就有,但虚函数指针在创建对象之后才有,因此无法调用虚构造函数

2.析构函数一般定义为虚函数:在动态多态时,子类继承父类,子类重写父类的虚析构函数,父类指针或引用指向子类,这样就可以通过父类指针调用子类的析构函数释放子类中开辟的内存。

18.为什么虚函数表中有两个析构函数

这是因为对象有两种构造方式,栈构造和堆构造,所以在对应的实现上,对象也有两种析构方法,其中堆上的对象和栈上的对象的析构不同之处在于,栈内存的析构不需要执行delete函数,会自动被回收。

19.为什么基类的析构函数要是虚函数

因为如果不设置成虚函数,析构的过程中只会调用到基类的析构函数而不会调用子类的析构函数,可能会产生内存泄漏。

20. volatile 关键字的作用?什么时候需要使用volatile 关键字

volatile关键字告诉编译器其修饰的变量是易变的,它会确保修饰的变量每次读操作都从内存里读取,每次写操作都将值写到内存里。volatile关键字就是给编译器做个提示,告诉编译器不要对修饰的变量做过度的优化,提示编译器该变量的值可能会以其它形式被改变。

volatile用于读写操作不可以被优化掉的内存,用于特种内存中。

(volatile 意思是易变的,是一种类型修饰符,在C/C++中用来阻止编译器因误认某段代码无法被代码本身所改变,而造成的过度优化。编译器每次读取 volatile 定义的变量时,都从内存地址处重新取值。

这里就有点疑问了,难道编译器取变量的值不是从内存处取吗?

并不全是,编译器有时候会从寄存器处取变量的值,而不是每次都从内存中取。因为编译器认为变量并没有变化,所以认为寄存器里的值是最新的,另外,通常来说,访问寄存器比访问内存要快很多,编译器通常为了效率,可能会读取寄存器中的变量。但是,变量在内存中的值可能会被其它元素修改,比如:硬件或其它线程等。)

21.各种强制类型转换的原理及使用

C++中有四个强制类型转换的关键字

1.static_cast:用于数据类型的强制转换,强制将一种数据类型转换为另一种数据类型。

用法:static_cast <类型说明符> (变量或表达式)

int a = 10;
int b = 3;
double result = static_cast<double>(a) / static_cast<double>(b);

它主要有如下几种用法:
    (1)用于类层次结构中基类和派生类之间指针或引用的转换
      进行上行转换(把派生类的指针或引用转换成基类表示)是安全的
      进行下行转换(把基类的指针或引用转换为派生类表示),由于没有动态类型检查,所以是不安全的
    (2)用于基本数据类型之间的转换,如把int转换成char。这种转换的安全也要开发人员来保证
    (3)把空指针转换成目标类型的空指针
    (4)把任何类型的表达式转换为void类型
    注意:static_cast不能转换掉expression的const、volitale或者__unaligned属性。

static_cast:可以实现C++中内置基本数据类型之间的相互转换。

2.const_cast:用于去除指向常量对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用

用法:const_cast<type_id> (expression)

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
    常量指针被转化成非常量指针,并且仍然指向原来的对象;
    常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

    const int a = 10;const int * p = &a;int *q;q = const_cast<int *>(p);*q = 20;    //fine

3.reinterpret_cast:reinterpret_cast主要有三种强制转换用途:改变指针或引用的类型、将指针或引用转换为一个足够长度的整形、将整型转换为指针或引用类型

用法:reinterpret_cast<type_id> (expression)

 type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。
    它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。

4.dynamic_cast:

用法:dynamic_cast<type_id> (expression)

(1)其他三种都是编译时完成的,dynamic_cast是运行时处理的,运行时要进行类型检查。

(2)不能用于内置的基本数据类型的强制转换。

(3)dynamic_cast转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回NULL。

(4)使用dynamic_cast进行转换的,基类中一定要有虚函数,否则编译不通过。

dynamic_cast用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”,

也即是基类对象的指针或引用转换为同一继承层次的其他指针或引用。

至于“先上转型”(即派生类指针或引用类型转换为其基类类型),本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是需要开销的

22.什么时候用指针,什么时候用引用

对于那些函数,它们只使用传递过来的值,而不对值进行修改

1)如果数据对象很小,如内置数据类型或小型结构,使用按值传递

2)如果数据对象是数组,则使用指向const的指针

3)如果数据对象是较大的结构,则使用const指针或者const引用,以提高程序的效率

4)如果数据对象是类对象,则使用const引用

对于那些函数,它们需要修改传递过来的值

1)如果数据对象很小,如内置数据类型或小型结构,则使用指针

2)如果数据对象是数组,则只能使用指针

3)如果数据对象是较大的结构,则使用指针或者引用,以提高程序的效率

4)如果数据对象是类对象,则使用引用

23.一般什么情况下会出现内存泄漏?怎么用C++在编码层面尽量避免内存泄漏。

内存泄漏是指程序向系统申请分配内存使用(new),用完却没有归还(delete),结果申请的那块内存程序不能使用,而系统也无法再将它分配给需要的程序。

如何避免:

1.将基类的析构函数设为虚函数

2.new和delete配对使用

3.使用智能指针

24.对面向对象的理解

C++面向对象的三大特性是封装、继承、多态。

C++面向对象编程就是把一切事物都变成一个个对象,用属性和方法来描述对象的信息,比如定义一个猫对象,猫的眼睛、毛发、嘴巴就可以定义为猫对象的属性,猫的叫声和走路就可以定义为猫对象的方法。

25.内存分区

代码区:存放函数体的二进制代码,由操作系统进行管理

全局区(静态区):存放全局变量,静态变量和常量

栈区:存放函数参数、局部变量等

堆区:由程序员进行手动分配和释放,若程序员不释放,在程序结束时有操作系统进行回收。

26.纯虚函数

纯虚函数是只有声明没有实现的虚函数,包含纯虚函数的类是抽象类,不能被实例化,只有实现了这个纯虚函数的子类才能生成对象。

27.深拷贝和浅拷贝

浅拷贝是对对象指针的复制,原对象和副本指向的是相同资源

深拷贝是开辟一片新的内存空间,将原对象的资源复制到新的空间,返回新空间的地址

深拷贝可以避免重复释放和写冲突。

28.悬挂指针和野指针、空指针、void指针

悬挂指针:当指针所指向的对象被释放后,指针的指向没有改变,还是指向被回收的内存地址

野指针:未初始化的指针

空指针:使用null或者nullptr初始化,不指向任何对象

Void指针:一种特殊类型的指针,可以存放任意对象的地址,任意类型的指针可以指向void指针,反之不行,void指针需要强制类型转换才能赋值给其他指针

29.new和malloc有什么区别

1.new和delete是c++的关键字/运算符,malloc和free是c++/c语言的标准函数

2.malloc需要显示地指定分配的内存大小,new不需要

3.new操作符从自由存储区上为对象动态分配内存空间,而malloc函数从堆上分配内存。注:凡是通过new操作符进行内存申请,该内存即为自由存储区

4.new操作符内存分配成功时,返回对象类型,无需进行类型转换,故new是符合类型安全的操作符,malloc返回void*,需要通过强制类型转换将void*指针转换成我们需要的类型

5.new操作符内存分配失败时,抛出bad_alloc异常,malloc内存分配失败时返回NULL

6.new操作符有构造和析构函数,在开辟空间的同时,会调用自定义对象的构造函数来完成初始化,malloc只会开辟空间

7.new相对malloc效率要低,因为new的底层封装了malloc

30.malloc的内存可以用delete释放吗

可以,但是一般不这么用。malloc和free是C语言中的函数,C++为了兼容C语言保留下来这一对函数。简单来说,new可以理解为,先执行malloc来申请内存,后调用构造函数来初始化对象,delete是先执行析构函数,后使用free来释放内存。若先new再使用free来释放空间的话,可能会出现一些错误。而先使用malloc,再使用delete的话没有问题。

31.malloc出来20字节内存,为什么free不需要传入20呢,不会产生内存泄漏吗?

因为不能保证程序员使用free时传入的参数是和malloc一致的,从而导致内存泄漏等问题。现在free的解决方式是让free函数自己确定要释放多少内存,可以使用的方式是在申请内存时多申请一些空间来存储内存大小,在free时再获取这个大小进行释放。

32.new[]和delete[]一定要配对使用吗?new[]和delete[]为何要配对使用?

1.不一定,当类型为int、float等内置类型时,可以不配对使用,但是建议还是配对使用。

2.new[]为一个数组申请内存时,编译器还会悄悄地在内存中保存一个整数,用来表示数组中元素的个数。因为在delete一块内存时,我们不仅要知道指针指向多大的内存,更重要的是要知道指针指向的数组中对象的个数。因为只有知道了对象数量才能一一调用它们的析构函数,完成对数组中所有对象的清理。如果使用的是delete,则编译器只会将指针所指的对象当作单个对象来处理。所以对于数组,需要使用delete[]来处理,符号[]会告诉编译器在delete这块内存时,先去获取保存的那个元素数量值,然后再进行一一清理。

33.基类的析构函数一般写成虚函数的原因

在析构指向子类的父类指针时,根据虚函数表找到子类的析构函数,从而正确释放子类对象的资源

34.什么情况下会调用拷贝构造函数

1)一个对象以值传递的方式传入函数体

2)一个对象以值传递的方式从函数返回

3)一个对象需要另一个对象进行初始化

35.为什么拷贝构造函数必须是引用传递而不是值传递

当一个对象需要以值方式传递时,编译器会生成代码调用它的拷贝构造函数以生成一个复本。如果类A的拷贝构造函数是以值方式传递一个类A对象作为参数的话,当需要调用类A的拷贝构造函数时,需要以值方式传进一个A的对象作为实参; 而以值方式传递需要调用类A的拷贝构造函数;结果就是调用类A的拷贝构造函数导致又一次调用类A的拷贝构造函数,这就是一个无限递归。

36.指针传递和引用传递的区别

指针传递的是变量“地址”,引用传的是变量“别名”。区别就是指针传递的时候是新声明了一个指针(指向相同地址)然后传进来,而引用则是将变量本身传进来(只不过换了个名字)。都可以对原值进行访问和修改,无需创建副本。

37.成员初始化列表的概念,为什么使用成员初始化列表会快一些

成员初始化列表就是在类或者构造函数中,在参数列表后以冒号为开头,逗号为分隔的一系列初始化字段

快:因为使用成员初始化列表进行初始化的话,会直接调用传入参数的拷贝构造函数进行初始化,省去了一次执行传入参数的默认构造函数的过程。

38.静态链接和动态链接

静态链接:在链接阶段,将源文件中用到的库函数与汇编生成的目标文件合并生成可执行文件;

优点:方便移植,执行速度快

缺点:占内存,每次更新都要重新链接

动态链接:把调用的函数所在的文件模块和调用函数所在文件的位置等信息链接进目标程序,程序在运行时再从文件模块中寻找相应的代码。

优点:应用灵活,不占内存

缺点:速度不如静态链接快

39.虚函数的实现原理

1)带有虚函数的类,编译器会为其分配一个虚函数表(用数组实现),里面记录了虚函数的地址,当此类被继承时,若子类重写了虚函数,则在子类的虚函数表中覆盖父类的虚函数地址,否则继承父类的虚函数地址。

2)实例化后,对象有一个虚函数指针,虚函数指针指向虚函数表,在程序运行时,通过虚函数指针找到虚函数表中对应的函数地址,调用虚函数

40.指针函数和函数指针

 指针函数:就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。

int *fun(int x,int y);

 函数指针:其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。

int (*fun)(int x,int y);

41.内存对齐

为什么要进行内存对齐?比如结构体的成员可以有不同的数据类型,所占的大小也不一样。同时,由于CPU读取数据是按块读取的,内存对齐可以使得CPU一次就可以将所需的数据读进来

对齐规则:第一个数据成员放在偏移量为0的地方,以后每个数据成员的起始位置都要从自身大小的整数倍开始存储

内存对齐的好处:1.加快内存读取效率2.便于在不同平台之间移植

内存对齐的缺点:空间浪费

42.TCP和UDP的区别

1.TCP是面向连接的,UDP是无连接的

2.TCP是可靠的,UDP是不可靠的

3.TCP是面向字节流的,UDP是面向数据报文的

4.TCP只支持点对点通信,UDP支持一对一,一对多,多对多

5.TCP有拥塞控制机制,UDP没有

6.TCP协议下双方发送接受缓冲区都有,UDP并无实际意义上的发送缓冲区,但存在接受缓冲区

43..arr、&arr[0]和&arr的不同

首先如果打印的话,三个打印的完全一样,都是数组首元素的地址。

arr是首元素的地址

&arr[0]是首元素的地址

&arr是整个数组元素的地址

arr+1和&arr[0]+1都只移动四个字节,但是&arr+1是整个数组的后一位

44. char a,char a[],char *a,char *[],char * *a 之间的区别

1. char a

定义了一个存储空间,存储的是char类型的变量

2. char a[]

是一个字符数组,数组中的每一个元素是一个char类型的数据

3. char *a

字符串的本质(在计算机眼中)是其第一个字符的地址,c和c++中操作字符串是通过内存中其存储的首地址来完成的
对于char a[]来说a代表的是数组的首地址,那么对char *a来说a代表的也是字符串的首地址
因此char a[]和char *a可以放到一块看,这两个没有本质区别。
但是要注意对于char s[]和char* a我们可以有`a=s`,但不能有`s=a`,因为创建数组的时候s的地址不为空已经确定,但是a是一个空指针,不能将非空的地址指向空指针

4. char *a[]

`*`的优先级是低于`[]`的,因此要先看`a[]`再看 `*`
因此这是一个char数组,数组中的每一个元素都是指针,这些指针指向char类型

`char *a[ ] = {"China","French","America","German"}`

5. char **a

两个**代表相同的优先级,因此从右往左看,即`char*(*a)`
char *a不就是一个字符串数组,a代表首地址。那么char * (*a)就是和char *a[]一样的数据结构

45.一维数组名和二维数组名的区别

不管是一维还是多维数组,都是内存中一块线性连续空间,因此在内存级别上,其实都只是一维。所以一维数组名是指向该数组的指针,二维数组名也是指向该数组的指针,但是+1之后,跳过的是一行。

46.二维数组名为什么不能直接赋值给二级指针?

一句话来说就是二维数组名是行指针,也就是指向数组的指针。而二级指针是指向指针的指针,它们不是同一类型。

47.用const和#define定义常量哪个更好?define宏常量和const常量的区别?是否可以做函数参数

1.类型和安全检查不同

宏定义是字符替换,没有数据类型的区别,同时这种替换没有类型安全检查,可能产生边际效应等错误;

const常量是常量的声明,有类型区别,需要在编译阶段进行类型检查

2.编译器处理不同

宏定义是一个"编译时"概念,在预处理阶段展开,不能对宏定义进行调试,生命周期结束于编译时期;

const常量是一个"运行时"概念,在程序运行使用,放在内存中的数据段中。

3.存储方式不同

宏定义是直接替换,不会分配内存,存储于程序的代码段中;

const常量需要进行内存分配,存储于程序的数据段中

是否可以做函数参数:宏定义和const常量可以在函数的参数列表中出现

48.typedef与#define的区别

typedef故名思意就是类型定义的意思,但是它**并不是定义一个新的类型而是给已有的类型起一个别名**。主要有两个作用,第一个是给一些复杂的变量类型起别名,起到简化的作用。第二个是定义与平台无关的类型,屏蔽不同平台之间的差异。在跨平台或操作系统的时候,只需要改typedef本身就可以
#define为一宏定义语句,本质就是文本替换

区别

1. 关键字typedef在编译阶段有效,由于是在编译阶段,因此typedef有类型检查的功能。\#define则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字符串替换,而不进行任何检查。

2. #define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用。而typedef有自己的作用域。

3. 对指针操作不同。

49.#include<>和include""的区别

include<>一般用来查找标准库文件所在目录,在编译器设置的include路径内搜索;

include "" 的查找位置是当前源文件所在目录

50.c++中四种变量存储类型总结

在C++语言中,变量的存储类共有如下四种: 

(1)auto存储类(自动存储类)

(2)static存储类 (静态存储类)

(3)extern存储类  (外部存储类)

(4)register存储类(寄存器存储类)
auto存储类,即自动存储类。在函数内部定义的变量,如果不指定其存储类,那么它就是auto类变量。这个是最常见的,所以我们不加关键字auto------auto int b

extern存储类,如果在一个文件中要引用另一个文件中定义的外部变量,则在此文件中应用extern关键字把此变量说明为外部的。

register存储类,为了提高某些自动类变量或函数参数的处理速度,可以在定义这些变量的类型说明符的前面加上register关键字,以通知编译系统为这些变量分配寄存器来存放其值。若使用register(而非auto)存储类标识代码块内的变量,编译器就会将变量缓存于处理器内的寄存器中,此种情况下不能对该变量或其成员变量使用引用操作符&以获取其地址,因为&只能获取内存空间中的地址

51.C++中this指针相关问题

1.什么是this指针,作用是什么?

类成员函数是怎么区分d1和d2对象的?怎么样就能做到把d1,d2分别赋值

类的成员函数本身就有一个隐含的参数,该参数就是所谓的this指针。在不同的对象调用的时候,编译器会自动将该对象的地址赋予"this"

class Date
{ 
public :void SetDate(int year , int month , int day){_year = year;_month = month;_day = day;}
private :int _year ; // 年int _month ; // 月int _day ; // 日
};
int main()
{Date d1, d2;d1.SetDate(2018,5,1);d2.SetDate(2018,7,1);return 0;}--------------------------------------------------------------
原函数名:void SetDate(int year,int month,int day)
实际上:void SetDate(int year,int month,int day,Date *this)
--------------------------------------------------------------
原代码:
_year = year;
_month = month;
_day = day;
实际代码:
_year = this->year;
_month = this->month;
_day = this->day;

什么是this指针,作用是什么?:this指针是C++类成员函数的一个隐含参数,当对象调用该成员函数的时候,编译器会将该对象的地址作为参数传入,通过this指针来对不同类进行操作,进而实现各个功能。

2.this指针存放在哪里?

1.this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传给this形参。所以对象中不存储this指针。

2.this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,也就是成员函数的其他参数正常都是存放在栈中,而this指针参数则是存放在寄存器中。

3.this指针可以为空吗?

this指针是类成员函数的一个隐含参数,不需要人为操作,因此它与其它成员函数不同,不存于栈中,而是在寄存器里。this指针可以为空,但有条件,当我们要进行的操作不需要this指针去指向某个对象(例如仅仅是打印一个东西)的时候就可以令它为空

4.this指针什么时候创建

this在成员函数的开始执行前构造,在成员函数的执行结束后清除

5.在成员函数中调用delete this会出现什么问题?

在类对象的内存空间中,只有数据成员和虚函数表指针,类的成员函数单独放在代码段中。在调用成员函数时,隐含传递一个this指针,让成员函数知道当前是哪个对象在调用它。

在调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要不涉及到this指针的内容,都能够正常运行。一旦涉及到this指针,如操作数据成员,调用虚函数等,就会出现不可预期的问题。

6.如果在类的析构函数中调用delete this,会发生什么?

会导致堆栈溢出。原因很简单,delete的本质是“为将被释放的内存调用一个或多个析构函数,然后释放内存”。显然,delete this会去调用本对象的析构函数,而析构函数中又调用delete this,形成无限递归,造成堆栈溢出,系统崩溃。

52.inline内联函数与宏定义

1.程序先执行函数调用之前的语句
2.流程的控制转移到被调用函数的入口处,同时进行参数传递
3.执行被调用函数中函数体的语句
4流程返回到函数调用的下一条指令处,将函数返回值带回
5接着执行主函数中未执行的语句。

这样的调用过程,就要求在转去被调用函数之前,要记下当时执行的指令的地址,还要保护现场(记下当时相关的信息),以便在函数调用之后,流程返回到先前记下的地址处,并且根据记下的信息恢复现场,然后继续执行。这些都要花费时间。
c++提供一种提高效率的方法,在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去,这种嵌入到主函数的代码称为内嵌函数,或者叫内置函数,或者叫内联函数。

区别:

1.参数类型安全性: 内联函数比宏定义更加类型安全。内联函数会对参数进行类型检查,而宏定义不会。这意味着,使用内联函数可以避免一些潜在的类型错误。
2.编译器优化: 内联函数是在编译期间展开的,因此它可以进行更多的编译器优化。而宏定义则是在预处理器展开,不能进行编译器优化。因此,使用内联函数通常可以获得更好的性能。
3.调试: 内联函数比宏定义更容易进行调试。因为内联函数是实际函数的一份副本,可以通过调试器跟踪到内联函数的执行过程。而宏定义则无法通过调试器进行调试。
4.名称空间: 内联函数位于名称空间中,而宏定义不属于任何名称空间。这意味着,内联函数可以避免名称冲突问题,而宏定义可能会导致名称冲突。
5.大小和可读性: 内联函数比宏定义更易于阅读和维护。宏定义的代码通常比较冗长,而内联函数则可以使用常规的C++语法编写,更加简洁易懂。另外,内联函数可以利用C++的函数重载和模板等特性,提高代码的可读性和可维护性。

53.explicit关键字

explicit主要用来防止隐式转换。**因为仅含一个参数的构造函数和除了第一个参数外其余参数都有默认值的多参构造函数承担了两个角色。 第一个是成为带参数的构造函数,第二个是一个默认且隐含的类型转换操作符(就是单参数的构造函数是一种隐含的类型转换符)

54.friend友元类和友元函数

**友元函数**能够使得普通函数直接访问类的保护数据和私有数据成员,避免了类成员函数的频繁调用,可以节约处理器开销,提高程序的效率,但所矛盾的是,即使是最大限度大保护,同样也破坏了类的封装特性,这即是友元的缺点,在现在cpu速度越来越快的今天我们并不推荐使用它。

**友元类**友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。    

55.c++运行机制

预处理、编译、汇编和链接​​​​​​​

1.预处理

C/C++语言最常见的预处理就是将所有的“#define”删除,并且展开所有的宏定义。而预处理其实还包括:处理所有的条件编译指令,比如“#if”、处理“#include”预编译指令、删除所有的注释、添加行号和文件名标识等。

2. 编译

​​​​​​​编译会将源代码由文本形式转换成机器语言,编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。

c++11

1.了解auto 和decltype 吗?

auto:可以让编译器在编译时就推导出变量的类型

decltype:用于推导表达式类型

int func() { return 0; };
decltype(func()) i; // i是intint x = 0;
decltype(x) y; // y是int
decltype(x + y) z; // z是int

2.谈一谈你对左值和右值的了解,了解左值引用和右值引用吗?

左值:在内存中有确定存储地址、有变量名、表达式结束依然存在的值。

左值引用:绑定到左值的引用,通过&来获得左值引用。

右值:在内存中没有确定存储位置、没有变量名,表达式结束就会销毁的值。

右值引用:绑定到右值的引用,通过&&来获得右值引用。

int a1 = 10; // 非常量左值
const int a2 = 10; // 常量左值int& b1 = a1; // 非常量左值引用
const int& b2 = a2; // 常量左值引用int&& c1 = 10; // 非常量右值引用
const int&& c2 = 10; // 常量右值引用,10是非常量右值  

3.了解移动语义和完美转发吗?

为什么需要右值引用,通过右值引用可以充分使用临时变量,减少不必要的拷贝,提高效率。         

移动语义:可以理解为转移所有权,拷贝是对于别人的资源,自己重新分配一块内存存储复制过来的资源,而对于移动语义,类似于转让或者资源窃取的意思,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用,通过C++11新增的移动语义可以省去很多拷贝负担,如何利用移动语义,主要通过移动构造函数。C++移动语义_c++ 可移动-CSDN博客

        完美转发:指可以写一个接受任意实参的函数模板,并转发到其它函数,目标函数会收到与转发函数完全相同的实参。转发函数实参是左值那目标函数实参也是左值,转发函数实参是右值那目标函数也是右值。聊聊C++中的完美转发 - 知乎 (zhihu.com)

4.平时会用到function、bind、lambda 吗,都什么场景下会用到?

std::function是C++11标准库中提供的一种可调用对象的通用类型,它可以存储任意可调用对象,如函数指针,函数对象,成员函数指针和lambda表达式。std::function类模板是一个类似于函数指针的类型,但它是可以处理任意可调用对象的,并且可以检查调用对象是否为空。

 基本语法:

std::function<return_type(parameter_types)> var_name;

int func(int x, int y) { return x + y; }
std::function<int(int, int)> f = func;class A {
public:int mem_func(int x) { return x * x; }
};
std::function<int(A*, int)> f2 = &A::mem_func;

 std::function对象可以像普通函数一样调用,并且可以使用bool类型的运算符来检查调用对象是否为空。

std::function<int(int, int)> f;
if (f)std::cout << f(1, 2) << std::endl;
elsestd::cout << "f is empty" << std::endl;

std::bind的头文件是 <functional>,它是一个函数适配器,接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。

std::bind主要有以下两个作用:

  • 将可调用对象和其参数绑定成一个防函数;
  • 只绑定部分参数,减少可调用对象传入的参数。

1.std::bind绑定普通函数

double callableFunc (double x, double y) {return x/y;}
auto NewCallable = std::bind (callableFunc, std::placeholders::_1,2);  
std::cout << NewCallable (10) << '\n';                       

1.bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind(callableFunc,_1,2)等价于std::bind (&callableFunc,_1,2);
2._1表示占位符,位于<functional>中,std::placeholders::_1;
3.第一个参数被占位符占用,表示这个参数以调用时传入的参数为准,在这里调用NewCallable时,给它传入了10,其实就想到于调用callableFunc(10,2);

2.std::bind绑定一个成员函数

class Base
{
public:void display_sum(int a1, int a2){std::cout << a1 + a2 << '\n';}int m_data = 30;
};
int main() 
{Base base;auto newiFunc = std::bind(&Base::display_sum, &base, 100, std::placeholders::_1);f(20); // should out put 120. 
}

1.bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
2.必须显式地指定&Base::diplay_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Base::display_sum前添加&;
3.使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &base;
3.绑定一个引用参数

5.enum 和enum class 有什么区别?

枚举作用域是指枚举类型成员名字的作用域,起自其声明之处,终止枚举定义结束之处。enum与class enum区别在于是否限定其作用域。C语言规定,枚举类型(enum)的成员的可见范围被提升至该枚举类型所在的作用域内。这被认为有可能污染了外部的作用域,为此,C++11引入了枚举类(enum class)解决此问题。
 

#enum
enum Sex
{Girl,				Boy		
};
// 错误,编译器提示 Girl,Boy重定义
enum Student
{Girl,				Boy	
};#enum class
enum class Sex
{Girl,				Boy		
};enum class Student
{Girl,				Boy	
};int main(int argc, char *argv[])
{Sex a = Sex::Gril; Student b = Student::Gril;//两者处于不同作用域下,不会重定义
}

枚举定义将被限制在枚举作用域内,并且不能隐式转换为整数类型,但是可以显式转化为整数类型,

enum class Sex
{Girl,				Boy	
};
int main(int argc, char *argv[])
{Sex a=Sex::Gril;int d1 =a; // 错误,无法从“Girl”隐式转换为“int”。int d2 = int(a); // 正确,显示将enum class转换为整数return 0;
}

STL

1.C++直接使用数组好还是使用std::array 好?std::array 是怎么实现的?

array是C++11中新提出来的容器类型,与内置数组相比,array是一种更容易使用,更加安全的数组类型,可以用来替代内置数组。作为数组的升级版,继承了数组最基本的特性,也融入了很多容器操作

数组初始化不能直接使用拷贝和赋值!!!数组的传递只能是遍历的形式来拷贝

和数组不同的是,array可以使用拷贝和赋值的形式进行初始化

array<int,10> ial1={0,1,2,3};

array<int,10> copy=ial1;//只要保证两者的类型一致就可以(包括元素类型和大小)

2.STL ⾥ resize 和 reserve 的区别?clear 是怎么实现的?

reserve()函数:会有可能将容量变大

(1)如果n大于容器现有的容量(capacity),比如你容器原来是100的容量,我现在指定n=200,那么就需要在自由内存区为整个容器重新分配一块新的更大的连续空间【因为vector是顺序容器,所以存储空间是连续的,如果之前的存储空间不够了,必须这样做】,然后将容器内所有的有效元素从旧位置全部复制到新位置,这个过程是调用拷贝构造函数,然后释放旧位置的所有存储空间,并调整容器的元素位置指示器。所以reserve的时候如果n比原来的大,结果只是让容器的冗余容量(即没有分配元素的存储区)变大,容器的实际大小,即元素个数并没有改变。

(2)如果n小于容器原来的容量,那么这个函数什么作用也没有了

resize()函数:会改变size的大小

(1)如果n大于容器当前的大小(即容器的size,这里和capacity无关),则在容器的末尾插入n-size()个初始值为c的元素;如果没有指定初始值,那就元素类型的默认构造函数来初始化。

(2)如果n小于容器当前的大小,则删除末尾的size()-n个元素,这样就导致容器的大小变了,size 变小了。但是这种类型的容器在删除一个元素的时候并不会释放元素本身的内存空间【这也是为了保留这块空间以避免将来要插入新元素的时候又要进行存储空间重分配】,所以容器的容量即capacity其实是没有改变的。

(3)n等于容器当前的大小,则什么也不做。

reserve和resize的共同点就是:都不缩减容器本身的容量。即对内存空间并没有影响

 clear实现:clear只是将vector的size置0,并不保证capacity为0,因此clear并不能释放vector已经申请的内存。

3.deque 的底层数据结构是什么?它的内部是怎么实现的?

4.map 和unordered_map 有什么区别?分别在什么场景下使用?

5.list 的使用场景?std::find 可以传入list 对应的迭代器吗?

6.string 的常用函数

=,assign() // 赋值
swap() // 交换
+=,append(),push_back() // 尾部添加字符
insert() // 插入字符
erase() // 删除字符
clear() // 清空字符
replace() // 替换字符
substr() // 截取子字符串

7.vector使用的注意点及其原因,频繁对vector调用push_back()对性能的影响和原因

如果需要频繁插入,最好先指定vector的大小,因为vector在容器大小不够的时候会重新申请一块大小为原容器两倍的空间,并将原容器的元素拷贝到新容器中,并释放原空间,这个过程是十分耗时和耗内存的。频繁调用push_bac()会使得程序花费很多时间在vector扩容上,会变得很慢,这种情况可以考虑用list。

8.C++中vector和list的区别

vector和数组类似,拥有一段连续的内存空间。能很好的支持随机存取,它的vector::iterator支持“+”,“+=”,“<”等操作符

list是由双向链表实现的,因此内存空间是不连续的,只能通过指针访问数据,所以list的随机存取非常没有效率,但能高效的进行插入和删除,不支持随机访问,因此list::iterator不支持“+”,“+=”,“<”等操作符

9.vector会迭代器失效吗?什么情况下会迭代器失效?

会。

对于序列容器vector、deque来说,使用erase(iterator)后,后边的每个元素的迭代器都会失效,但是后边每个元素都会往前移动一个位置,但是erase会返回下一个有效的迭代器

对于关联容器map、set来说,使用了erase(iterator)后,当前元素的迭代器失效,但是其结构是红黑树,删除当前元素,不会影响到下一个元素的迭代器,所以在调用erase之前,记录下一个元素的迭代器即可。

对于list来说,它使用了不连续分配的内存,并且它的erase方法也会返回下一个有效的iterator,因此上面两种正确的方法都可以使用。

操作系统

C++ Qt常用面试题整理(不定时更新)_qt面试题-CSDN博客

相关文章:

c++面试题

1.static的使用 1&#xff09;修饰局部变量&#xff1a;在函数内部使用static修饰局部变量&#xff0c;会使它成为静态局部变量。静态局部变量只会被初始化一次&#xff0c;且只有在第一次调用该函数时才会被初始化&#xff0c;之后每次调用该函数时都会保留上一次的值.从原来…...

高精度加法,减法,乘法,除法(上)(C语言)

前言 加&#xff0c;减&#xff0c;乘&#xff0c;除这些运算我们自然信手捏来&#xff0c;就拿加法来说&#xff0c;我们要用c语言编程算ab的和&#xff0c;只需让sum ab即可&#xff0c;可是这是局限的&#xff0c;我们都知道int的表示的最大值为2147483647&#xff08;32位…...

C++新经典模板与泛型编程:SFINAE特性的信息萃取

用成员函数重载实现is_default_constructible 首先介绍一个C标准库提供的可变参类模板std::is_default_constructible。这个类模板的主要功能是判断一个类的对象是否能被默认构造&#xff08;所谓默认构造&#xff0c;就是构造一个类对象时&#xff0c;不需要给该类的构造函数…...

java单人聊天

服务端 package 单人聊天;import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import…...

nodejs环境安装

node安装 wget https://mirrors.tuna.tsinghua.edu.cn/nodejs-release/v20.8.0/node-v20.8.0-linux-x64.tar.gz tar xf node-v20.8.0-linux-x64.tar.xz -C /usr/local/ ln -s node-v20.8.0-linux-x64 nodevim /etc/profile.d/node.sh export PATH$PATH:/usr/local/node/binnp…...

R语言进行正态分布检验

查了很多资料&#xff0c;还是比较模糊 Kolmogorov-Smirnov检验&#xff08;K-S检验&#xff09;广泛用于正态性检验和其他分布的拟合检验。适用于中等到大样本。 Lilliefors检验是K-S检验的一种变体&#xff0c;专门为小样本设计。其通过使用更准确的临界值来提高对小样本的适…...

什么是SPA(Single Page Application)?它的优点和缺点是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

由于找不到xinput1_3.dll,无法继续执行代码的多种解决方法指南,xinput1_3.dll文件修复

当玩家或用户在启动某些游戏和应用程序时&#xff0c;可能会遭遇到一个系统错误提示&#xff1a;“由于找不到xinput1_3.dll,无法继续执行代码l”。这种情况通常指出系统中DirectX组件存在问题。以下我们将介绍几种常用的解决方法&#xff0c;并提供详细的操作步骤。 一.找不到…...

Vue---Echarts

项目需要用echarts来做数据展示&#xff0c;现记录vue3引入并使用echarts的过程。 1. 使用步骤 安装 ECharts&#xff1a;使用 npm 或 yarn 等包管理工具安装 ECharts。 npm install echarts 在 Vue 组件中引入 ECharts&#xff1a;在需要使用图表的 Vue 组件中&#xff0c;引入…...

uni-app实现返回刷新上一页

方案一 通过监听器实现 page1 uni.$on("refresh", function(data) {if(data.page "page2") {this.reload()} })page2 methods: {handleBack() {uni.$emit("refresh", {page: "page2"})uni.navigateBack()} }方案二 通过页面实例实…...

centos服务器安装docker和Rabbitmq

centos服务器 一 centos安装docker1 安装docker所需要的依赖包2配置yum源3查看仓库中所有的docker版本4安装docker5 设置docker为开机自启6验证docker是否安装成功 二 使用docker安装RabbitMQ拉取RabbitMQ镜像创建并运行容器 一 centos安装docker 1 安装docker所需要的依赖包 …...

【Redis】Redis高级特性和应用(慢查询、Pipeline、事务、Lua)

目录 Redis的慢查询 慢查询配置 慢查询操作命令 慢查询建议 Pipeline 事务 Redis的事务原理 Redis的watch命令 Pipeline和事务的区别 Lua Lua入门 安装Lua Lua基本语法 注释 标示符 关键词 全局变量 Lua中的数据类型 Lua 中的函数 Lua 变量 Lua中的控制语句…...

【pytorch】深度学习入门一:pytorch的安装与配置(Windows版)

请支持原创&#xff0c;认准DannisTang&#xff08;tangweixuan1995foxmail.com&#xff09; 文章目录 第〇章 阅读前提示第一章 准备工作第一节 Python下载第二节 Python安装第三节 Python配置第四节 Pycharm下载第五节 Pycharm安装第六节 CUDA的安装 第二章 Anaconda安装与配…...

安装postgresql驱动及python使用pyodbc指定postgresql驱动调用postgresql

注&#xff1a;Python解释器版本(32位/64位)和postgresql驱动版本(32位/64位)需一致。 一、安装postgresql驱动 https://www.postgresql.org/ftp/odbc/versions/msi/ &#xff08;1&#xff09;32位&#xff1a; &#xff08;2&#xff09;64位&#xff1a; 双击安装。全程默…...

【OpenCV】计算机视觉图像处理基础知识

目录 前言 推荐 1、OpenCV礼帽操作和黑帽操作 2、Sobel算子理论基础及实际操作 3、Scharr算子简介及相关操作 4、Sobel算子和Scharr算子的比较 5、laplacian算子简介及相关操作 6、Canny边缘检测的原理 6.1 去噪 6.2 梯度运算 6.3 非极大值抑制 6.4 滞后阈值 7、Ca…...

Course1-Week3-分类问题

Course1-Week3-分类问题 文章目录 Course1-Week3-分类问题1. 逻辑回归1.1 线性回归不适用于分类问题1.2 逻辑回归模型1.3 决策边界 2. 逻辑回归的代价函数3. 实现梯度下降4. 过拟合与正则化4.1 线性回归和逻辑回归中的过拟合4.2 解决过拟合的三种方法4.3 正则化4.4 用于线性回归…...

Dockerfile 指令的最佳实践

这些建议旨在帮助您创建一个高效且可维护的Dockerfile。 一、FROM 尽可能使用当前的官方镜像作为镜像的基础。Docker推荐Alpine镜像&#xff0c;因为它受到严格控制&#xff0c;体积小&#xff08;目前不到6 MB&#xff09;&#xff0c;同时仍然是一个完整的Linux发行版。 FR…...

Drools 入门:折扣案例

1. 安装 在idea软件中安装Drools 插件&#xff0c;我这里是直接搜索Drools就可以搜到 2. 实现入门案例 2.1 配置pom.xml文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi&q…...

微信小程序中生命周期钩子函数

微信小程序 App 的生命周期钩子函数有以下 7 个&#xff1a; onLaunch(options)&#xff1a;当小程序初始化完成时&#xff0c;会触发 onLaunch&#xff08;全局只触发一次&#xff09;。onShow(options)&#xff1a;当小程序启动或从后台进入前台显示时&#xff0c;会触发 on…...

“无忧文件安全!上海迅软DSE文件加密软件助您轻松管控分公司数据!

许多大型企业集团由于旗下有着分布在不同城市的分支机构&#xff0c;因此在规划数据安全解决方案时&#xff0c;不适合采用市面上常见的集中式部署方式来管控各分部服务器&#xff0c;而迅软DSE文件加密软件支持采用分布式部署的方式来解决这一问题。 企业用户只需在总部内部署…...

详解线段树

前段时间写过一篇关于树状数组的博客树状数组&#xff0c;今天我们要介绍的是线段树&#xff0c;线段树比树状数组中的应用场景更加的广泛。这些问题也是在leetcode 11月的每日一题频繁遇到的问题&#xff0c;实际上线段树就和红黑树 、堆一样是一类模板&#xff0c;但是标准库…...

C语言——指针的运算

1、指针 - 整数 #include<stdio.h> #define N_VALUES 5 int main() {flout values[N_VALUES];flout *vp;for(vp&values[0];vp<&values[N_VALUES]&#xff1b;) //指针的关系运算{*vp0; //指针整数} } 2、指针 - 指针 #include<stdio.h> int main() …...

Apache Hive(部署+SQL+FineBI构建展示)

Hive架构 Hive部署 VMware虚拟机部署 一、在node1节点安装mysql数据库 二、配置Hadoop 三、下载 解压Hive 四、提供mysql Driver驱动 五、配置Hive 六、初始化元数据库 七、启动Hive(Hadoop用户) chown -R hadoop:hadoop apache-hive-3.1.3-bin hive 阿里云部…...

python入门级简易教程

Python是一种高级编程语言&#xff0c;由Guido van Rossum于1991年创建。它是一种通用的、解释型的、高级的、动态的、面向对象的编程语言。 Python的编程哲学是简洁明了&#xff0c;强调代码的可读性和简洁性&#xff0c;使开发人员能够快速开发出正确的代码。Python被广泛用…...

模拟一个集合 里面是设备号和每日的日期

问题&#xff1a; 需要模拟一个集合 里面是设备号和每日的日期 代码如下&#xff1a; static void Main(string[] args){string equipmentCodePar "";DateTime time DateTime.Now; // 获取当前时间DateTime startDate time.AddDays(1 - time.Day);//获取当前月第一…...

antdesign前端一直加载不出来

antdesign前端一直加载不出来 报错&#xff1a;Module “./querystring” does not exist in container. while loading “./querystring” from webpack/container/reference/mf at mf-va_remoteEntry.js:751:11 解决方案&#xff1a;Error: Module “xxx“ does not exist …...

排序算法介绍(一)插入排序

0. 简介 插入排序&#xff08;Insertion Sort&#xff09; 是一种简单直观的排序算法&#xff0c;它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。插入排序在实现上&#xff0c;通常…...

2023新优化应用:RIME-CNN-LSTM-Attention超前24步多变量回归预测算法

程序平台&#xff1a;适用于MATLAB 2023版及以上版本。 霜冰优化算法是2023年发表于SCI、中科院二区Top期刊《Neurocomputing》上的新优化算法&#xff0c;现如今还未有RIME优化算法应用文献哦。RIME主要对霜冰的形成过程进行模拟&#xff0c;将其巧妙地应用于算法搜索领域。 …...

RNN:文本生成

文章目录 一、完整代码二、过程实现2.1 导包2.2 数据准备2.3 字符分词2.4 构建数据集2.5 定义模型2.6 模型训练2.7 模型推理 三、整体总结 采用RNN和unicode分词进行文本生成 一、完整代码 这里我们使用tensorflow实现&#xff0c;代码如下&#xff1a; # 完整代码在这里 imp…...

Rust UI开发(五):iced中如何进行页面布局(pick_list的使用)?(串口调试助手)

注&#xff1a;此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库&#xff0c;用于为rust语言程序构建UI界面。 这是一个系列博文&#xff0c;本文是第五篇&#xff0c;前四篇链接&#xff1a; 1、Rust UI开发&#xff08;一&#xff09;&#xff1a;使用iced构建UI时…...

Linux学习笔记2

web服务器部署&#xff1a; 1.装包&#xff1a; [rootlocalhost ~]# yum -y install httpd 2.配置一个首页&#xff1a; [rootlocalhost ~]# echo i love yy > /var/www/html/index.html 启动服务&#xff1a;[rootlocalhost ~]# systemctl start httpd Ctrl W以空格为界…...

数据结构算法-插入排序算法

引言 玩纸牌 的时候。往往 需要将牌从乱序排列变成有序排列 这就是插入排序 插入排序算法思想 先看图 首先第一个元素 我默认已有序 那我们从第二个元素开始&#xff0c;依次插入到前面已有序的部分中。具体来说&#xff0c;我们将第二个元素与第一个元素比较&#xff0c;…...

安装Kuboard管理K8S集群

目录 第一章.安装Kuboard管理K8S集群 1.安装kuboard 2.绑定K8S集群&#xff0c;完成信息设定 3.内网安装 第二章.kuboard-spray安装K8S 2.1.先拉镜像下来 2.2.之后打开后&#xff0c;先熟悉功能&#xff0c;注意版本 2.3.打开资源包管理&#xff0c;选择符合自己服务器…...

网络安全行业大模型调研总结

随着人工智能技术的发展&#xff0c;安全行业大模型SecLLM&#xff08;security Large Language Model&#xff09;应运而生&#xff0c;可应用于代码漏洞挖掘、安全智能问答、多源情报整合、勒索情报挖掘、安全评估、安全事件研判等场景。 参考&#xff1a; 1、安全行业大模…...

Linux AMH服务器管理面板本地安装与远程访问

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装…...

Sharding-Jdbc(3):Sharding-Jdbc分表

1 分表分库 LogicTable 数据分片的逻辑表&#xff0c;对于水平拆分的数据库(表)&#xff0c;同一类表的总称。 订单信息表拆分为2张表,分别是t_order_0、t_order_1&#xff0c;他们的逻辑表名为t_order。 ActualTable 在分片的数据库中真实存在的物理表。即上个示例中的t_…...

zookeeper集群 +kafka集群

1.zookeeper kafka3.0之前依赖于zookeeper zookeeper是一个开源&#xff0c;分布式的架构&#xff0c;提供协调服务&#xff08;Apache项目&#xff09; 基于观察者模式涉及的分布式服务管理架构 存储和管理数据&#xff0c;分布式节点上的服务接受观察者的注册&#xff0c…...

2022年全国大学生数据分析大赛医药电商销售数据分析求解全过程论文及程序

2022年全国大学生数据分析大赛 医药电商销售数据分析 原题再现&#xff1a; 问题背景   20 世纪 90 年代是电子数据交换时代&#xff0c;中国电子商务开始起步并初见雏形&#xff0c;随后 Web 技术爆炸式成长使电子商务处于蓬勃发展阶段&#xff0c;目前互联网信息碎片化以…...

Python版本与opencv版本的对应关系

python版本要和opencv版本相对应&#xff0c;否则安装的时候会报错。 可以到Links for opencv-python上面查看python版本和opencv版本的对应关系&#xff0c;如图&#xff0c;红框内是python版本&#xff0c;绿框内是opencv版本。 查看自己的python版本后&#xff0c;使用下面…...

【开源视频联动物联网平台】LiteFlow

LiteFlow是一个轻量且强大的国产规则引擎框架&#xff0c;可用于复杂的组件化业务的编排领域。它基于规则文件来编排流程&#xff0c;支持xml、json、yml三种规则文件写法方式&#xff0c;再复杂的逻辑过程都能轻易实现。LiteFlow于2020年正式开源&#xff0c;2021年获得开源中…...

家用智能门锁——智能指纹锁方案

智能指纹锁产品功能&#xff1a; 1&#xff1a;指纹识别技术&#xff1a;光学传感器、半导体传感器或超声波传感器等。 2&#xff1a;指纹容量&#xff1a;智能指纹锁可以存储的指纹数量&#xff0c;通常在几十到几百个指纹之间。 3&#xff1a;解锁时间&#xff1a;指纹识别和…...

Qt6 QRibbon 一键美化Qt界面

强烈推荐一个 github 项目&#xff1a; https://github.com/gnibuoz/QRibbon 作用&#xff1a; 在几乎不修改任何你自己代码的情况下&#xff0c;一键美化你的 UI 界面。 代码环境&#xff1a;使用 VS2019 编译 Qt6 GUI 程序&#xff0c;继承 QMainWindow 窗口类 一、使用方法 …...

JAVA IO:NIO

1.阻塞 IO 模型 ​ 最传统的一种 IO 模型&#xff0c;即在读写数据过程中会发生阻塞现象。当用户线程发出 IO 请求之后&#xff0c;内核会去查看数据是否就绪&#xff0c;如果没有就绪就会等待数据就绪&#xff0c;而用户线程就会处于阻塞状态&#xff0c;用户线程交出 CPU。当…...

Python 在控制台打印带颜色的信息

#格式&#xff1a;  设置颜色开始 &#xff1a;\033[显示方式;前景色;背景色m #说明&#xff1a; 前景色 背景色 颜色 --------------------------------------- 30 40 黑色 31 41 红色 32 …...

SQL Server 数据库,创建触发器避免数据被更改

5.4触发器 触发器是一种特殊类型的存储过程&#xff0c;当表中的数据发生更新时将自动调用&#xff0c;以响应INSERT、 UPDATE 或DELETE 语句。 5.4.1什么是触发器 1.触发器的概念 触发器是在对表进行插入、更新或删除操作时自动执行的存储过程&#xff0c;触发器通常用于强…...

C语言实现植物大战僵尸(完整版)

实现这个游戏需要Easy_X 这个在我前面一篇C之番外篇爱心代码有程序教你怎么下载&#xff0c;大家可自行查看 然后就是需要植物大战僵尸的素材和音乐&#xff0c;需要的可以在评论区 首先是main.cpp //开发日志 //1导入素材 //2实现最开始的游戏场景 //3实现游戏顶部的工具栏…...

基于YOLOv8深度学习的火焰烟雾检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…...

【C++】手撕string思路梳理

目录 基本思路 代码实现 1.构建框架&#xff1a; 2.构建函数重载 3.迭代器&#xff1a; 4.遍历string 5.resetve 开空间&#xff0c;insert任意位置插入push_back,append,(按顺序依次实现) 6.erase删除&#xff0c;clear清除&#xff0c;resize缩容 7.流插入&#xff0…...

【数据结构和算法】确定两个字符串是否接近

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1操作 1 的本质&#xff1a;字符可以任意排列 2.2操作 2 的本质&#xff1a;出现次数是可以交换的 2.…...

[足式机器人]Part2 Dr. CAN学习笔记-Ch0-1矩阵的导数运算

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Ch0-1矩阵的导数运算 1. 标量向量方程对向量求导&#xff0c;分母布局&#xff0c;分子布局1.1 标量方程对向量的导数1.2 向量方程对向量的导数 2. 案例分析&#xff0c;线性回归3. 矩阵求导的链…...