面试之C++(篇三:C++11)

目录

1.为什么引入nullptr

2.C++11的强制类型转换简述

3.C++11强制类型转换的应用场景

4.C++11为什么引入了强制类型转换

5.简述智能指针

6.为什么引入智能指针?

7.左值引用与右值引用

8.为什么引入右值引用?

9.简述内联函数

10.内联函数与宏函数、普通函数相比的优势

11.内联函数的应用场景

12.const与constexpr,为什么要引入constexpr?


1.为什么引入nullptr

(1)在原先的C/C++中常用NULL来表示空,而在不同的编译器中NULL的定义是不同的,例如#define NULL 0,#define NULL (void*)0。有函数void func(int),void func(void*),在不同编译器下可能会调用不同的重载函数,或者出现语义错误。

(2)在C++中禁止 void* 隐式转换成其他类型,因此在C++中NULL被定义为0。

因此引入了nullptr用于区分NULL和0,nullptr可以隐式转换成任意指针,其类型是nullptr_t。

 

2.C++11的强制类型转换简述

c++11定义了四种强制类型转换

(1)static_cast:

  • 基本内置类型之间转换;
  • 基于类层次的基类与派生类之间指针或者引用的转换(上行转换安全,下行转换不安全);
  • 将任意类型转换为void*;
  • 将空指针转换成目的类型的指针;

(2)dynamic_cast:

  • 基于类层次的基类与派生类之间指针或者引用的转换(上行、下行转换都有类型安全检查);
  • 上行转换与static_cast效果一样,下行转换也进行了类型安全转换,只有当要转换类型的指针指向对象的实际类型与转换的类型相同时才能正确转换,否则返回NULL,引用出错的话抛出异常;
  • 只有基类中包含了虚函数时,dynamic_cast编译才能通过;

(3)const_cast:

  • 将const转换成非const;
  • 只能作用于指针或者引用;

(4)reinterpret_cast:

  • 在不改变其二进制值的情况下,重新解释其值;
  • 可以任意类型之间的转换;
  • 可以将指针或引用转换成足够长的整型,再将整型转换成指针或引用,实现一个数据的交互作用;
  • 用于辅助哈希函数;

 

3.C++11强制类型转换的应用场景

(1)基本内置类型之间的转换用static_cast;

(2)基类与派生类之间指针或引用的转换用dynamic_cast;

(3)去除指针或引用的const用const_cast;

(4)不同类型的指针或引用转换用reinterpret_cast(慎用!)

 

4.C++11为什么引入了强制类型转换

(1)原先C风格强制类型转换没有类型安全检查,实现任意类型的强制转换,在编译阶段无法检查出错误,运行时才可能会报错;而C++11的强制类型转换有类型安全检查,在编译阶段就会检查报错。

(2)C风格的强制类型转换为 (type-id) expression ,不方便查找转换的代码;而C++11提供了不同情况下不同的类型转换方式,利用类模板来更好的强制转换的位置,更便于代码的阅读和调试。

 

5.简述智能指针

通过引入一个引用计数来实现内存的自动释放,当引用计数为0时自动释放内存。

在介绍智能指针前,先说下auto_ptr,即所有权占用指针。当这种指针被赋值或者拷贝时,用户会失去对其的控制,因此不支持拷贝赋值;此外在该指针的析构函数中只能调用delete,因此不能用于管理数组对象。

(1)unique_ptr:独占式指针

  • 该指针具备唯一特性,因此不支持拷贝赋值,但是可以作为返回值返回,实质上使用的移动操作;
  • 当一个unique_ptr指向一个对象时,不允许其他指针指向该对象,当指向或初始化出错时会显示编译错误,这是auto_ptr不具备的;
  • 不能用shared_ptr或unique_ptr来初始化unique_ptr。

(2)shared_ptr:共享式指针

  • 该指针引入了一个引用计数变量,用于记录指向shared_ptr指向对象的所有指针的数量;
  • 支持多个指针指向同一个对象,同时更新引用计数;
  • 当引用计数为0时,自动释放内存。

(3)weak_ptr:弱指针

  • 该指针指向一个对象,不会影响对应的引用计数;
  • 引入这个指针的原因是,当两个shared_ptr相互引用时,引用计数无法为0,导致死锁,因此利用weak_ptr实现两个shared_ptr的相互访问,避免了死锁带来的内存泄漏问题;
  • 不能保证所指对象的有效性。w

 

6.为什么引入智能指针?

在C++中指针需要手动释放,当指针量多且代码复杂时,很容易出现忘记释放内存,调用没有申请内存空间的指针等内存泄漏问题,人为无法很好的解决此问题,因此通过引入引用计数,当引用计数为0时自动释放相应的内存空间,从而智能化的解决指针带来的内存泄漏问题。

 

7.左值引用与右值引用

(1)左值与右值的本质区别在于是否能够取其地址。

(2)两者的区别如下:

  • 绑定的对象不同。左值引用绑定的是返回左值引用的函数、赋值、下标、解引用、前置递增递减;而右值引用只能绑定右值。
  • 左值具备持久性;而右值一般为临时变量或者即将被销毁的变量。
  • 右值可以自由接管引用对象的内容。

 

8.为什么引入右值引用?

(1)右值引用使用的移动构造,减少了临时对象的拷贝操作带来的性能损耗;

(2)确定模板函数参数转发的实际类型;

 

9.简述内联函数

(1)在inline关键字来定义内联函数,一般在类内定义的成员函数,编译器默认为内联函数。

(2)inline只是给编译器的一个建议,编译器可以选择性忽略。

(3)inline函数在函数运行时才进行展开,因此不用调用栈进行栈空间的申请和现场的保护和恢复,效率更高。

 

10.内联函数与宏函数、普通函数相比的优势

(1)从类型安全检查上看,内联函数与普通函数都有类型安全检查,而宏函数没有类型安全检查,inline函数类型安全时才进行展开。

(2)从代码量上看,宏函数在预处理阶段就进行了宏展开,因此生成的目标文件可能会很大;而inline函数则只在运行时才进行展开。

(3)从效率上看,内联函数在运行时才展开,而普通函数在调用时,需要申请栈空间,保存调用语句的下一执行语句地址,参数压栈等操作,因此内联函数的效率更高。

 

11.内联函数的应用场景

(1)适用于优化规模小、更直接且频繁使用的函数;

(当代码规模小时,函数调用的耗时可能比函数体执行的时间长,因此内联函数一般少于5条语句)

(2)inline不能有复杂的分支语句,如if-else、switch-case、for、while、for-while等;

 

12.const与constexpr,为什么要引入constexpr?

(1)const注重的是“只读”特性,即const修饰的值不能被修改;而constexpr注重修饰的值为常量表达式。

(2)constexpr修饰的值在编译阶段就要能够确定,并用于传参给编译期就要确定参数值的函数或是模板;而const修饰的值需要在运行时才能够确定。

在大部分情况下,const和constexpr作用相同。

 

下一篇:面试之C++(篇四:其他常见问题)

以上内容均是个人理解总结,若有错误欢迎指出!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值