面经系列1:

一、

1、字节对齐

计算机在访问特定类型变量时经常需要在特定的内存地址访问,这样就需要各种类型的数据按照一定的顺序去排列,而不是顺序的一个接一个的排放,这就是对齐。
一些平台对某些特定类型的数据只能从某些特定地址开始存取。如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。
字节对齐的规则:
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数),一般来讲,在32位机器上,默认对齐数是4字节, 64位机器上默认对齐数是8字节. 我们可以通过预编译命令#pragma pack(n),n=1,2,4,8,16 来改变这一系数,其中的n就是你要指定的“对齐系数”。
规则一、 结构体中每个数据成员在结构体中的起始位置,应该是 MIN(这个数据成员的字节数, 对齐系数)。
规则二、整个结构体的大小,应该是MIN(其最长数据成员所占字节, 对齐系数)的整数倍。

具体案例请参考:
原文链接:https://blog.csdn.net/Jxianxu/article/details/113684871

2、内联函数

增加了 inline 关键字的函数称为“内联函数”。
(1)内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处,就像整个函数体在调用处被重写了一遍一样。以时间换取空间,或增加空间消耗来节省时间
(2)inline的使用是有所限制的,inline只适合代码简单的函数使用,不能包含复杂的结构控制语句例如while、switch,
(3)inline函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思
(4)关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用
(5)内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。 如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

3、堆区栈区

堆区:一般由程序员通过 new 开辟空间,进行分配和释放,若程序员不释放,则程序结束时由操作系统回收
栈区:由编译其自动分配释放,存放函数的参数值以及局部变量等;
全局区:存放全局变量和静态变量以及常量,在程序结束后由操作系统释放;
代码区:存放函数体的二进制代码,由操作系统管理创建,代码区时共享的,对于频繁被执行的程序,只需要存有一份代码即可;
举例:

// 全局变量属于全局区,由操作系统管理释放
int g_a = 1;
int g_b = 2;
int main(void)
{
	cout << "g_a 的地址为:\t"<< int(&g_a) << endl;
	cout << "g_b 的地址为:\t" << int(&g_b) << endl;
	// 创建普通的局部变量,属于栈区
	int a = 10;
	int b = 20;	
	cout << "a 的地址为:\t" << int(&a) << endl;
	cout << "b 的地址为:\t" << int(&b) << endl;
	// 创建静态变量,属于全局区
	static int s_a = 40;
	static int s_b = 50;
	cout << "s_a 的地址为:\t" << int(&s_a) << endl;
	cout << "s_b 的地址为:\t" << int(&s_b) << endl;
	// 程序员自己创建变量,属于堆区
	int* d_a = new int(10);
	int* d_b = new int(20);
	cout << "d_a 的地址为:\t" << int(d_a) << endl;
	cout << "d_b 的地址为:\t" << int(d_b) << endl;
}

参考链接:
https://www.cnblogs.com/zhaozhibo/p/14941915.html

4、New delete mollc 区别

运算符是语言自身的特性,它有固定的语义,而且编译器也知道意味着什么。就像 ±*/ 一样,由编译器解释语义,生成相应的代码。
库函数是依赖于库的,没有库就没有它,也就是一定程度上独立于语言的。理论上,编译器不知道也不关心函数的作用,编译器只保证编译函数,以及调用该函数时参数和返回值符合语法
(1)malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
(2)new 将调用构造函数,而malloc不能;delete将调用析构函数,而free不能。对象在创建的同时要自动执行构造函数,对象消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能把执行构造函数和析构函数的任务强加于malloc/free。
(3) new与delete带具体类型的指针,malloc与free返回void类型的指针。

5、虚函数

虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定

纯虚函数

想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

6、内存泄露

内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

7、链表和数组

数组:需要一块连续的内存空间来存储,随机访问效率高,但占用内存较大。扩容时需要再申请一块更大的内存空间,将原数组拷贝进去,非常费时。
链表:将一组零散的内存块串起来使用,没有大小的限制,天然支持动态扩容
访问时数组时间复杂度为O(1),链表时间复杂度为O(n)
增加删除时数组时间复杂度为o(n),链表时间复杂度为O(1)

8、公共继承,什么时候用

8.1继承:

保持原有的特性基础上进行扩展,增加功能
好处:可以减少重复的代码
语法:class 子类(派生类) :继承方式 父类(基类)

8.2 继承方式:

1、公共继承 :
公有继承方式,会把基类的公有成员(变量和函数)继承到子类公有成员,保护成员变成基类的保护成员,但是私有成员子类也一样不可以访问
2、保护继承
保护继承方式,会把基类的公有成员或者保护成员(变量和函数)变成子类的保护成员,但是私有成员子类也一样不可以访问
3、 私有继承
私有继承方式的,就是在继承时,把protected变成private,它需要注意的事项为:
(1) 基类公有成员,子类中继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
(2). 基类保护成员,子类中继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
(3) 基类私有成员,子类一样不可以访问基类的私有成员,
继承中的对象属性:父类的所有非静态属性都会被子类继承。

9、时间复杂度和空间复杂度

算法的时间复杂度是一个函数,它定性描述该算法的运行时间。
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度

10、二叉树的遍历顺序

二叉树的遍历顺序有前序遍历、中序遍历、后序遍历和层次遍历

11、指针和引用的区别

1、指针是一个变量,存储的是一个地址,指向内存的一个存储单元;
引用是原变量的一个别名,跟原来的变量实质上是同一个东西。
2、指针可以有多级,引用只能是一级
3、指针可以在定义的时候不初始化,引用必须在定义的时候初始化
4、指针可以指向NULL,引用不可以为NULL

12、堆排序的步骤

13、对容器有什么了解,vector

定义

在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器。很简单,容器就是保存其它对象的对 象,当然这是一个朴素的理解,这种“对象”还包含了一系列处理“其它对象”的方法
容器还有另一个特点是容器可以自行扩展

通用容器的分类

STL 对定义的通用容器分三类:顺序性容器、关联式容器和容器适配器。
顺序性容器 是 一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。这个位置和 元素本身无关,而和操作的时间和地点有关,顺序性容器不会根据元素的特点排序而是直接保存了元素操作时的逻辑顺序。比如我们一次性对一个顺序性容器追加三 个元素,这三个元素在容器中的相对位置和追加时的逻辑次序是一致。
的。
关联式容器 和 顺序性容器不一样,关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置 入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。
容器适配器 是一个比较抽象的概念, C++的 解释是:适配器是使一事物的行为类似于另一事物的行为的一种机制。容器适配器是让一种已存在的容器类型采用另一种不同的抽象类型的工作方式来实现的一种机 制。其实仅是发生了接口转换。那么你可以把它理解为容器的容器,它实质还是一个容器,只是他不依赖于具体的标准容器类型,可以理解是容器的模版。或者把它 理解为容器的接口,而适配器具体采用哪种容器类型去实现,在定义适配器的时候可以由你决定
在这里插入图片描述

14、C++中的指针占几个字节

取决于是64位编译模式还是32位编译模式(注意,和机器位数没有直接关系)
在64位编译模式下,指针的占用内存大小是8字节
在32位编译模式下,指针占用内存大小是4字节

15、对数据结构的了解

数据结构,直白地理解,就是研究数据的存储方式。如何存储具有复杂关系的数据更有助于后期对数据的再利用。
数据结构大致包含以下几种存储结构:顺序表、链表、栈、队列、树结构、图结构
顺序表(底层实现靠数组)时,需要提前申请一定大小的存储空间,这块存储空间的物理地址是连续
使用链表存储数据时,是随用随申请,因此数据的存储位置是相互分离的,换句话说,数据的存储位置是随机的。
栈和队列隶属于线性表,是特殊的线性表,因为它们对线性表中元素的进出做了明确的要求。
中的元素只能从线性表的一端进出(另一端封死),且要遵循“先入后出”的原则,即先进栈的元素后出栈。
队列中的元素只能从线性表的一端进,从另一端出,且要遵循“先入先出”的特点,即先进队列的元素也要先出队列。
存储结构适合存储具有“一对多”关系的数据。
存储结构适合存储具有“多对多”关系的数据

16、如何理解面向对象(面向对象的三大特性六大原则)

面向对象三大特性(封装、继承和多态)

(1)封装的意义:将属性和行为作为一个整体,表现生活中的事物,将属性和行为加以权限控制。
class类名{ 访问权限:属性/行为; };
类在设计时,可以把属性和行为放在不同的权限下,并加以控制。
struct默认权限是public;
class默认权限是private;
(2)继承性:让某种类型对象获得另一个类型对象的属性和方法。继承可以扩展已存在的代码
(3)多态性:同一事物表现出不同事物的能力,即向不同对象发送同一消息,不同的对象在接收时会产生不同的行为(重载实现编译时多态,虚函数实现运行时多态)。多态的目的则是为了接口重用

六大原则

面向对象的六大设计原则:
<1>单一职责原则:单一职责原则是在描述一个类其中应该只包含一组和其功能相关的成员函数和数据,而不应该再含有其他功能,
当一个类中含有较多不想关的成员变量或者函数时,我们应该考虑将这个类拆分成多个类
单一职责原则的优点:
单一职责原则可以降低类的复杂度,提高系统的可维护性。
单一职责实际也减少了类的冗余性,提高了类的重组性和功能单一化
消除耦合,减小由业务变化引起的代码僵化
单一职责原则解决的问题:
当有类A,需要有两个功能T1和T2时,当T1的功能需要改变时,可能会导致T2的功能有障碍,因此在设计时就需要将T1和T2两个
分别构建类Fun1和Fun2,来分别完成他们的功能

<2>里式替换原则

里式替换原则:里式替换原则是依赖于继承和多态的,当有父类出现的地方,子类也可以出现,并且子类对象可以替换父类对象,并且
使用者不需要知道是父类还是子类,但是反之却不行。因为父类中不一定有子类的方法。

里式替换的优点:里式替换可以提高代码的可重用性
保证子类中含有父类的所有属性,
缺点:子类中有时候可能就比较冗余

<3>依赖倒置原则:依赖倒置原则在讲各个类之间是通过接口去耦合,而不是和类的接口的实现方法相关
是和类方法的地层实现不相关的。

<4>开放封闭原则:开放封闭原则讲的是对于修改我们应该封闭,而对于拓展我们是应该开放

<5>迪米特原则: 对象与对象之间应该使用尽可能少的方法来关联,避免千丝万缕的关系。
一个对象应该对其他对象有最少的了解。一个类应该对自己需要耦合或调用的类知道的最少,
类的内部如何实现与调用者或者依赖者没有关系,调用者或者依赖者只需知道它需要的方法即可。
一般是伴随着类的组合出现

<6>接口隔离原则:接口隔离原则推荐在设计类时应该使用最小的接口,使用多个单一功能的接口比使用一个总的接口要好。

二、使用步骤

1.引入库

代码如下(示例):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

2.读入数据

代码如下(示例):

data = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

该处使用的url网络请求的数据。


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值