2021-11-15 科创面试记录

科创讯飞面试记录

1.了解c++14 17的特性吗?
—i>const 只读 constexptr 常量:const是在运行阶段,Constexptr是在编译阶段,比如constexptr int a=5,这种。因为是在运行阶段就已经确认的,所以在链接或者运行的阶段的话是不需要在做其他计算处理,如果是Const他的初始化会延迟到运行。
可以参考这个https://blog.csdn.net/QLeelq/article/details/122688259
ii>auto 自动类型推导,让编译器通过初始值替开发人员分析表达式所属的类型。忽略顶层const (int const *p) 保留底层const(const int * p)
iii>decltype 也是类型推导,但是不需要实际计算表达式的值.(保留顶层const)
iv>lamda表达式:是一个匿名函数,不需要命名函数或者对象,有的地方只需要调用一次的就可以使用Lambda表达式来实现。主要是【捕获列表,用于捕获上下文的变量供Lamda表达式中使用,=值传递 &引用传递】【参数列表,就是函数中的参数,如果不需要参数的可以省略】【可变规则 默认是一个const函数,加mutable可以取消常量】【返回类型】【函数体】
vi>右值和右值引用:
右值:右值是相对于左值来说的,左值就是一些有内存空间的值,比如int a = 10;a 就是左值,10就是右值。
右值引用:绑定到左值上面的引用。让绑定的右值暂时生存,但是本身他不能绑定任何左值。他的主要存在的意义是主要是两个 一个是移动语义,一个是完美转发。
移动语义就是说将一个对象进行转移到另外一个对象,用于减少不必要的临时对象的创建拷贝和销毁。这点是相对拷贝语义相对的。因为拷贝构造函数的深拷贝构造场景中,是需要申请内存空间的。那使用移动语义的移动构造函数就是使用了当前对象的内存空间,随后将这个临时对象指针置位空。
std::move 移动函数,主要是将左值转换为右值。转换后的左值后续是不能再继续使用的。std::move实现主要是通过 引用折叠+static_cast+remove_refrence::type实现的。参数是右值引用,两个引号,左值传入进去后就从&&&变为了&,remove_refrence::type剥夺了他的引用,然后通过static_cast<T&&>类型转换就可以实现。
如果是穿进去的是右值,引用折叠&&&& -->&&,static_cast转换还是不变
https://blog.csdn.net/weixin_38739598/article/details/109692726

完美转发:
因为左值或者右值在函数调用的时候,作为参数,他都是已经被转化为了左值。在函数调用的时候无法区分开到底是左值还是右值。
完美转发的作用是把参数不管是左值还是右值,通过std::forward转发之后,左值依然是左值,右值还是右值,属性不变。
他的地层实现是通过函数重载实现的,两个实现的核心都是引用折叠+remove_reference剥夺原始参数的引用,通过引用折叠判断传进来的是一个&的左值还是两个&&的右值,然后通过static_cast进行类型转换为&&. 如果是左值,&–>static_cast转换变成&&&,引用折叠为&。如果是右值,转换为&&&&折叠为&&
https://www.cnblogs.com/zl1991/p/16033811.html
2.智能指针说一下
Unique_ptr shared_ptr weak_ptr
然后就把具体使用场景说一下就可以
Unique_ptr 实现:
1.首先是不能使用赋值的方式把控制权赋值给其他指针,因此需要他没有拷贝构造函数和=重载。需要转移的话只能只用std::move,同时需要写移动构造函数和移动赋值函数用来构造unique_ptr。用来保证一个对象只有一个所有权
https://www.cnblogs.com/xgcode/p/13526928.html
share_ptr实现:
需要重载赋值构造函数、拷贝构造函数、析构函数,因为需要处理use_count。但是如果是多线程的话,count++或者–不是院子操作,需要枷锁
weak_ptr用来解决shared_ptr互相引用引起死锁导致资源泄露的问题
成员变量:
count:用于统计当前引用技术个数
3.右值引用知道吗?右值引用的使用场景是什么?
见问题1
4.map的插入 []和Insert有什么区别,从源码角度说一下哪个更高效
先说结论:
如果被插入的值是没有重复的,用Insert。如果是修改值的话使用[]
原因:
插入操作:[]会需要先创建出一个Pair,如果他的value是个类,那么就会再进行调用一次value的构造函数,并且[]会返回一个value对象的引用,然后对于value再赋值给这个引用。相当于是一次构造+一次拷贝构造。如果用insert,就直接只创建一个pair,只进行了一次构造
更新操作:使用[]返回的引用已经指向一个存在元素,再给这个元素赋值的时候不会发生构造,直接就进行了赋值。如果使用Insert会先构造出一个Pair,事后需要对这个pair对象进行析构。

代码对比上可参考这个博主的代码
https://blog.csdn.net/weixin_39703605/article/details/108190578

5.vector怎么高效删除
高效这个暂时还不知道,有知道的可以讲讲
删除:
第一个就是vector自带的erease函数,但是这个函数erease后会使得迭代器指向下一个元素。

for(auto iter=vec.begin();iter!=vec.end();)
{
    if(满足条件)
    {
        iter = vec.erase(iter); // 注意这块直接返回了一个Iter
    }
    else
    {
        iter++; //不然就Iter++
    }
}

其次删除元素还可以使用remove。只是说将元素放到了vector的尾部,size大小是没有发生变化的。但是erease是变化了
6.unodermap和map有什么区别,什么场景下用Map
map 底层实现的话是红黑树,如果使用场景里面有大量的插入操作,那么就会面临着排序问题。影响效率。unorderedmap底层是Hash表,查询的时间复杂度是o(1),但是建立hash表的时间长。对数据排序没有要求的就用unordermap 有要求的话用map
7.装饰器模式
8.单例模式怎么保证全局只有一个(恶汉懒汉不行,面试官建议看一下开源源码)
9.策略模式和命令模式有什么区别
10.Gtest框架是什么
11.说一下gtest里面的参数化测试
Test_p+Getparam()+INSTANTIATE_TEST_CASE_P 实现,主要是一次把参数都传进去。

代码可参见
https://www.cnblogs.com/coderzh/archive/2010/03/19/gtest_demo.html

12.说说适量加班怎么个适量
反正就说自己能加就行了,我这个菜鸡本来就不行还说自己不接受过度加班==
记不太清了,剩下的想起来补充
补充
13 stl里面的Find和c++的 find有什么区别,为什么更推荐用stl.find函数
14.map如果使用自定义的排序,要怎么排
https://blog.csdn.net/qq_38762282/article/details/124068932

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值