1.怎么限制对象只能建立在栈上?
重载new/delete操作符或设置为私有
2.怎么限制对象只能建立在堆上?
- 将析构函数设定为私有,再定义一个共有的释放函数(有问题无法实现多态,因为析构函数要设置为虚函数)
- 将构造函数设为protect,然后提供一个public函数进行构造
3.虚函数可以内联吗?
不实现多态的虚函数可以内联。内联是编译时期的处理,多态是运行时期的处理
4.虚函数说明一下?
编译器为每个含有虚函数的类共建一张虚表,里面有虚函数的入口地址。每个对象有一个vptr指针,负责指向虚函数表的地址(vptr指针在构造完成的时候完成初始化)
5.构造和析构函数需要定义为虚函数吗?
构造函数不能定义为虚函数。vptr指针构造完成才能确认指向,所以构造函数不能定义为虚函数 析构函数必须定义为虚函数。否则多态时无法析构父类方法
6.delete和delete[]区别?
delete[]会多次调用析构函数
7.什么是野指针?
- 指向被释放的内存
- 指向没有权限的内存
8.野指针产生的原因?
- 指针未初始化为nullptr,指向是随机的
- 内存被释放后,指向内存的指针没有被置空
- 指针指向一块栈上的内存,这块内存作用域结束就被释放了
9.C++的空类都会创建那些函数
- 默认构造
- 拷贝构造
- 赋值运算符
- 取值运算符
- const取值运算符
- 析构函数
10.sizeof怎么计算的?
字节对齐计算
11.static修饰符
- 修饰类内变量:类外初始化、与类绑定不与对象绑定、类内所有函数都能调用、存储在全局静态区
- 修饰全局变量:只能被初始化一次,只能当前文件访问
- 修饰类外局部变量:只能被初始化一次、可见域结束不会释放
- 修饰类外函数:当前文件可见
- 修饰类内函数:类外可直接调用,函数内只能用static变量
12.C++的内存分布(32位寻址空间)?
内核空间 栈(向下)最大2M系统块,不会产生内存碎片 堆(向上)最大3G手动分配,会产生内存碎片 全局常量区 代码段
13.内存泄露的几种情况?
- new或者malloc后没有delete或者free
- 没有对基类的析构函数加虚函数
- 比如文件句柄、socket等资源没有释放
- shard_ptr循环引用
14.C++源码到可执行文件的步骤?
预处理-编译-汇编-链接
15.memset可以初始化一个对象吗?
当有虚函数存在的时候不行,memset会将vptr指针赋空值
16.sizeof一个空类的大小?
每个对象都有独一无二的地址,为了保存地址所以设置为1
17.左值和右值
- 左值是可寻址的变量,有持久性;
- 右值一般是不可寻址的常量,或在表达式求值过程中创建的无名临时对象,短暂性的。
- 能用&取到地址的是左值,其余都是右值
18.move和forward
- forward:将一个传进函数的参数原封不动的传递出去(这里的原封不动指的是如果传进来之前为右值,那么就以右值传出去,如果传进来是左值,那么就以左值传出去
- move:是一个强制类型转换,将左值类型转换为右值类型,主要目的就是方便调用右值类型的构造函数,和static_cast<>(),差不多类似的作用,用了move的对象对其它对象进行初始化时会调用右值引用构造函数也是转移构造函数,这个构造函数的作用就是将对象的内容直接给要初始化的对象,而不是拷贝一个过去
19.移动构造(右值引用的使用)
- 浅拷贝的问题,是因为两个指针共同指向一片内存空间,若第一个指针将其释放,另一个指针的指向就不合法了。
- 深拷贝的问题,新建了一块与待复制结构完全相同的空间,耗时长。
- 移动拷贝:将临时对象管理的内存移动到a,将临时对象地址设置为nullptr,防止浅拷贝的问题
引用坍缩
有模板的代码里,对于类型参数的推导结果可能是引用。我们可以略过一些繁复的语法规则,要点是:
- 对于
template <typename T> foo(T&&)这样的代码,如果传递过去的参数是左值,T的推导结果是左值引用;如果传递过去的参数是右值,T的推导结果是参数的类型本身。 - 如果
T是左值引用,那T&&的结果仍然是左值引用——即type& &&坍缩成了type&。 (只有右值引用才会被推导成右值引用,其他都是左值引用)
noexcept作用
noexcept是C++11中的一个关键字,用于表示一个函数不会抛出任何异常。在函数声明或定义中,可以使用noexcept关键字来显式地说明该函数是否会抛出异常。如果一个函数标记为noexcept,则系统在运行时就不会对该函数进行异常处理,从而提高程序的性能和效率。
- 常量表达式的优化。对于标记为noexcept的函数,编译器可以将其用作常量表达式的计算,从而提高程序的性能。
- 异常安全性。由于标记为noexcept的函数不会抛出异常,在使用该函数的代码中,可以更加自信地使用不带RAII(资源获取即初始化)的代码,以提高代码的异常安全性。
- 代码优化。标记为noexcept的函数可以使编译器在优化代码中利用更多的技术,例如函数内联、跳过异常处理代码等,从而提高程序的效率。
文章来自多方面的学习积累,请各位大佬指正