C++面试必备

Posted AI不学习

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++面试必备相关的知识,希望对你有一定的参考价值。

1.什么是虚函数,什么是纯虚函数

虚函数是允许被自己的子类重新定义的成员函数。

虚函数声明:virtual returntype func(parameter);引入虚函数的目的是为了动态绑定

纯虚函数声明:virtual returntype funcparameter=0;引入纯虚函数是为了派生接口以实现多态(使派生类仅仅只是继承函数的接口)

2.基类为什么需要虚析构函数?

是为了防止内存泄漏,如果不是虚函数的话想去借助父类指针去销毁子类对象的时候,就不能去销毁子类对象。假如没有虚析构函数,释放一个由基类指针指向的派生类对象时,不会触发动态绑定,则只会调用基类的析构函数,不会调用派生类的。派生类申请的空间就得不到释放,这样就会导致内存泄漏。

 

3.i是一个整数的时候i++++i哪一个更快?他们的区别是什么?

几乎一样,i++返回的是i的值,++i返回的是i+1的值,也就是说++i是一个确定的值,是一个可以修改的左值。

 

4.vectorreservecapacity的区别

Reserve()是让容器预留空间,避免再次分配内存capacity()返回在重新进行分配以前所能容纳的元素数量

在使用STL中的vector时,对于sizecapacityresizereserve的使用要认真理解。

vectorsize()capacity()属性分别对应着resize(size_type)reserve(size_type)这两个方法。

我们先看size()capacity()属性的区别:

size:表示实际容器中保持的元素的个数

capacity:表示在发生重新分配之前允许存放多少元素。

 

resize(size_type) :对某个vector容器调用resize方法会在该容器的尾部增加或者删除一些元素,使容器达到指定的大小。

reserve(size_type):对于vector容器调用reserve方法仅仅是设置了capacity的值。

注意:reserve(size_type)只是改变了capacity的值,此时这些内存空间可能还是“野”的,如果使用[]操作费进行数据访问,就可能出现数据访问越界的情况。

下面我们给出一些测试程序来说明:

 

#include<iostream>

#include<vector>

 

using namespace std;

 

int main(void)

{

vector<int>vecSize;

vector<int>vecCapacity;

 

vecSize.resize(2);

cout<< "vecSize.size() = " << vecSize.size() << ",vecSize.capacity() = "<< vecSize.capacity() <<endl;

 

vecCapacity.reserve(2);

cout<< "vecCapacity.size() = " << vecCapacity.size() <<", vecCapacity.capacity() = " << vecCapacity.capacity()<< endl;

 

return0;

}

输出如下:


 

 

从输出结果我们可以看出resize方法会使vector容器拥有指定个数的元素,而reserve只是改变capaciy的值。

 

接下来我们来看看下个例子:

 

       


  }

 

 上面的测试程序在运行时会接收到std::out_of_range异常。这也说明了reserve只是改变capaciy的值此时这些内存空间可能还是“野”的。如果使用[]操作符进行访问,可能出现数组越界问题。

 

最后,我们在来看看resize方法对size和capacity的影响。

 

 


 


     

这是vector的一个好处它的capacity()机制减少了内存分配的次数。等于说resize()还替我们做了reserve()的事。

 

 

5.如何初始化conststatic数据成员

   通常在类外申明 static成员,但是 staticconst的整型(bool,char,int,long可以在类中声明且初始化, static const的其他类

型必须在类外初始化(包括整型数组)

6. static和 const分别怎么用,类里面 static和const可以同时修饰成员函数吗?

static的作用:

对变量:

1.局部变量:

在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。

 

1)内存中的位置:静态存储区

2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显式初始化)

3)作用域:全局静态变量在声明他的文件之外是不可见的,准确的讲从定义之处开始到文件结尾。

2.全局变量

在全局变量之前加上关键字static,全局变量就被定义成了一个全局静态变量。

1)内存中的位置,静态存储区(静态存储区在整个程序运行期间都存在)

2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非它被显示的初始化)

3)作用域:全局静态变量在声明他的文件之外是不可见的,准确的讲是从定义开始处到结尾。

 

注意:static修饰全局变量,并未改变其存储位置和生命周期,而是改变了其作用域,使当前文件外的源文件无法访问该变量,好处是:

(1)不会被其他文件所访问,修改

(2)其他文件中可以使用相同的名字的变量不会发生冲突。对全局函数也是隐藏作用,而普通变量只要定义了  任何地方都能使用,使用的时候需要声明所有的.c文件,只能定义一次普通全局变量,但是可以声明多次(外部链接)注意全局变量的作用域是全局范围,但是某个文件中使用,必须先声明

3.对于类中

1.成员变量

用static修饰类的数据成员实际使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象。因此,static成员必须在类外进行初始化(初始化格式:intbase::var = 10;)而不能再构造函数中进行初始化,不过也可以const修饰static数据成员在类内初始化。因为静态成员属于类,而不是属于某个对象,如果类内初始化,会导致每个对象都含有静态成员这是矛盾的。

    特点:

   1.不要试图在头文件中定义(初始化)静态成员变量,在大多数情况下,这样做会引起重复定义这样的错误。即使加上#ifndef #define #endif或者#pragma once也不行。

   2.静态数据成员可以成为成员函数的可选参数,而普通数据成员则不行。

  3.静态数据超过那样的类型可以是所属类的类型,而普通数据成员则不行,普通数据成员只能声明为所属类类型的指针或者引用。

 2.成员函数

 1)用static修饰成员函数,使这个类只存在这一份函数,所有对象共享函数,不含this指针

2)静态成员是可以独立访问的,也就是说无需创建任何对象实例就可以访问,base::func(5,3)static成员函数在类外定义时,不需要加static修饰。

3)在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中的静态成员,因为静态成员函数不含this指针。

 

不可以同时用const和static修饰成员函数

 

C++编译器在实现const的成员函数的时候为了确保该函数不能修饰类的实例状态,会在函数中添加一个隐式的参数constthis*,但当一个成员为static的时候,该函数是没有this指针的。也就是说此时cosnt的用法和static是冲突的

我们也可以这么样理解:两者的语义是矛盾的,static的作用是表示该函数只作用于类型的静态变量上,与类的实例没有关系,而const的作用是确保函数不能修改类的实例状态,与类型的静态变量没有关系,因此不能同时用他们。

const的作用:

1.限定变量为不可修改的

2.限定成员函数不可以修改任何数据成员

3.const与指针:

Const char *p :表示指向的内容不能改变。

Char * const p:就是将P声明为常指针,它的指针不能改变,是固定的,但是它的内容可以改变


以上是关于C++面试必备的主要内容,如果未能解决你的问题,请参考以下文章

面试必备 | C++ 中的各种特性

面试必备 | C++ 中的各种特性

冒泡排序 面试必备

MySQL数据库之大厂面试必备技能v8.0.27

Nginx面试题(史上最全 + 持续更新)

MyBatis面试题(史上最全+不断升级)