第三次面试题目 (反省中!!)

1.C++动态加载库

动态库
动态库又称动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。DLL 是一个包含可由多个程序同时使用的代码和数据的库。Windows下动态库为.dll后缀,在linux下为.so后缀,下文以linux为例进行说明。

动态库加载方式
链接加载
在程序运行时将链接的动态库装载入进程实体(内存中)。应用程序需要包含动态库对应的头文件来调用动态库的方法,并链接动态库提供方法支持。

动态加载
使用dlopen,dlsym, dlclose和dlerror来动态地将动态库装载到当前进程实体中,头文件#include <dlfcn.h>。
 

1.dlopen

将指定的动态库以特定的方式装载到当前进程实体,并返回一个可操作的句柄,用以后续获取函数地址等操作

void *dlopen(const char *filename, int flag);

2.dlsym

从指定的(由dlopen的返回值指定)库中获得指定的函数(即函数,第二个参数为函数名)。

void *dlsym(void *handle, const char *symbol);

3.dlclose

可将关闭卸载动态库。注意,实际是减掉一个对动态库的引用(ref),仅当减到0时才会触发卸载动态库的操作。

int dlclose(void *handle);
 

4.dlerror

返回一个字符串用以描述错误。

char *dlerror(void);
 

函数加载动态库


动态库动态加载
第一步:生成dll:
此步骤参考动态库静态加载中第一步:生成dll:

第二步:加载dll:
新建vs项目
添加主程序入口函数.cpp文件(包含main函数的源文件)
使用Windows库函数加载dll
LoadLibraryA 加载dll
GetProcAddress 获取函数地址
FreeLibrary 释放句柄
添加第一步生成dll中的.dll文件.lib文件
.lib可随意放置,使用时,指定正确的路径即可
放置.dll文件在和.exe文件同一目录下

一个链接:

visual studio上C++库加载方式及方法:动态库静态加载、动态库动态加载、静态库加载_无敌小峰哥的博客-CSDN博客


2.静态成员在那个内存里,

在类成员变量中,必要的时候可以用static将成员变量修饰为静态,来提高代码高效性、节省内存空间;

在程序执行时,先将class文件加载进内存中的方法区,然后主方法进栈,主方法执行过程中会定义变量(基本类型变量在栈中存放、引用类型变量在堆中存放  [引用类型就是封装好的类嘛]),调用方法(在栈内存中,可以理解,主方法也是方法,所以方法执行的时候都要进栈,执行完弹出,至于方法中的执行过程和主方法就相一致了)。

类的成员变量并不能决定自身的存储空间位置。决定存储位置的是对象的创建方式。

即:

如果对象是函数内的非静态局部变量,则对象,对象的成员变量保存在栈区。

如果对象是全局变量,则对象,对象的成员变量保存在静态区。

如果对象是函数内的静态局部变量,则对象,对象的成员变量保存在静态区。
 


3.list和vector的区别

1.vector数据结构
vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。
因此能高效的进行随机存取,时间复杂度为o(1);
但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。
另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内存拷贝。

2.list数据结构
list是由双向链表实现的,因此内存空间是不连续的。
只能通过指针访问数据,所以list的随机存取非常没有效率,时间复杂度为o(n);
但由于链表的特点,能高效地进行插入和删除。


4.list的优点

list 有序可重复,存入顺序和取出顺序完全相同


5. 解析json xml数据,有没有用第三方工具解析过

XML的解析
XML是一种常见的存储数据方式,在Android平台中内部很多地方都使用了XML存储,如轻量级的SharedPreferences类的存储就是使用的XML文件。
XML解析主要有三种方式,SAX(Simple API for XML),DOM(Document Object Mode)和Android附带的PULL解析器解析XML文件。

JSON解析
JSON是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

XML和JSON 已经常用的解析工具_Alisck的博客-CSDN博客

iOS开发之数据解析:Json、XML - 简书 (jianshu.com)


6.一个空类的大小

C++标准指出,不允许一个对象(当然包括类对象)的大小为0,不同的对象不能具有相同的地址。这是由于:

  • new需要分配不同的内存地址,不能分配内存大小为0的空间
  • 避免除以 sizeof(T)时得到除以0错误

故使用一个字节来区分空类。


7.mysql查询数据怎样才能效率高

.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 

3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

 4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20 

可以这样查询: select id from t where num=10 union all select id from t where num=20

5.in 和 not in 也要慎用,否则会导致全表扫描,如: 

select id from t where num in(1,2,3) 

对于连续的数值,能用 between 就不要用 in 了: 

select id from t where num between 1 and 3

 6.下面的查询也将导致全表扫描: 

select id from t where name like '%abc%' 

若要提高效率,可以考虑全文检索。

 7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描: select id from t where num=@num 

可以改为强制查询使用索引: 

select id from t with(index(索引名)) where num=@num

 8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where num/2=100 

应改为: 

select id from t where num=100*2

 9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如: 

select id from t where substring(name,1,3)='abc' --name以abc开头的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

 11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。 

12.不要写一些没有意义的查询,如需要生成一个空表结构: select col1,col2 into #t from t where 1=0 

这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样: 

create table #t(...)

 13.很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num)

 14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中 有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

 15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。

 16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

 17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和 连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

 18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

 19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

 20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

 21.避免频繁创建和删除临时表,以减少系统表资源的消耗。

 22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事 件,最好使用导出表。 

23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

 24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

 25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

 26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。 

27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时 间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

 28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

 29.尽量避免大事务操作,提高系统并发能力。 

30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。


8.c++11标准和C++17标准

两个链接:

C++11、C++14、C++17、C++20区别、string、char*、char[]区别_干干干就完了的博客-CSDN博客_c++11和c++17的区别

c++11/14/17标准你了解多少_xiaomu_347的博客-CSDN博客_c++11和c++14标准的区别


9.设计模式和观察者模式

设计模式三杰:单例,工厂,观察者。这三个使用的频率最高。

观察者模式
定义
广播机制
许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

代码实现
抽象主题(Subject)角色:也叫抽象目标类,里面又一个观察者类的列表,和增加、删除观察者对象的实际方法,以及通知所有观察者的抽象方法。
具体目标类:它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个响应更新的抽象方法。
具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
测试:创建具体目标对象,创建多个观察者,并将他们添加到目标对象中。然后具体目标对象内部做出改变,并通知所有观察者。各个观察者做出响应。

优点
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系但是具体实现的类不耦合。符合依赖倒置原则。也就是高层抽象模块依赖,而底层实现模块不相互依赖。
目标与观察者之间建立了一套广播通讯,触发机制。


缺点
当观察者对象很多时,通知的发布会花费很多时间,因为每个观察者都要更新自己的数据,影响程序的效率。
如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。


10.extern声明

两个链接:

extern函数声明(转) - greathuman - 博客园 (cnblogs.com)

extern的使用详解(多文件编程)——C语言 - 蓝海人 - 博客园 (cnblogs.com)


11.父类有构造函数,  派生类没有构造函数,派生类怎样生成构造函数。

继承的同时  在子类的构造函数之后   : 父类构造函数  

差不多!!


 12.如何多表查询实现

两个链接:

怎样实现多表查询_青丝若水三千�的博客-CSDN博客_怎么实现多表查询

SQL基础-->多表查询_Leshami的博客-CSDN博客_多表查询


13..有没有做过 堆排序,哈希排序

 哈希排序:

一个 链接:

哈希排序算法_CairBin的博客-CSDN博客_哈希排序


 14.动态加载so 函数怎样实现

两个链接:

Linux 动态加载并调用动态库(.so)方法介绍_enjoy嚣士的博客-CSDN博客_linux 动态加载so

C/C++动态加载So编程_给大佬递杯卡布奇诺的博客-CSDN博客_c++ 动态加载so


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值