c++一些面试可能问到的问题

c++和JAVA

1.C++支持多重继承,JAVA不支持,但是有接口的概念,接口拥有多态特性。

2.C++支持运算符重载,JAVA不支持。

3.C++支持默认函数参数,JAVA不支持。

4.C++支持自动强制类型转换,JAVA不支持。

5.C++有结构和联合体,JAVA只有类。

6.JAVA有垃圾自动回收机制,但是C++需要程序员去管理对内存的申请和释放,C++有析构函数。

7.JAVA提供的标准库功能更强,包括网络编程、多线程等,C++没有。

8.JAVA为解释型语言,源代码经过编译成为字节码然后由JVM解释运行,C++为编译型语言,源代码经过编译和链接之后生成可以执行的二进制代码,导致JAVA可以跨平台运行但是执行速度慢。

9.JAVA为纯面向对象语言,所有代码必须在类中实现,C++兼具面向对象和面向过程语言。

10.JAVA没有指针,C++有。

C和C++

1.C是纯面向过程的语言,C++是面向过程和面向对象的语言。

2.C++使用new和delete分配释放内存,C使用malloc和free。

3.C++有引用这个概念,C没有。

4.C++有类,C没有。

5.C++有函数重载C没有。

面向对象

面向对象是一种基于对象的、基于类的软件开发思想,面向对象具有继承、封装、多态的特性。

继承:子类可以具有父类的方法或者重新定义追加属性和方法。

多态:为不同数据类型的实体提供统一的接口。

允许将子类类型的指针赋值给父类类型的指针,把不同的子类对象都当做父类来看。

C++的多态通过晚绑定技术实现,通过在基类的函数前面加上virtual关键字,在派生类中重写该函数,运行的时候就会根据对象的实际类型来调用响应的函数。

实现通过虚表:编译器在编译的时候,发现类中有虚函数就会为每个包含虚函数的类创建一个虚表,这个表是一个一维数组,数组中存放了每个虚函数的地址,每个对象都有一个虚表指针vptr,这个指针指向对象所属类的续表,运行时根据对象类型去初始化vptr,让vptr指向正确类的虚表。(在构造函数中初始化)

纯虚函数:是虚函数后=0

抽象类是至少包括一个纯虚函数的类。

函数的多态性:一个函数被定义成多个不同参数的函数。

什么函数不可以是虚函数

普通函数

友元函数

构造函数(vptr是在构造函数中初始化的,没有vptr没法使用虚函数)

内联函数

静态成员函数

析构函数为什么必须是虚函数

1.继承类的析构函数如果不是虚函数,派生类的新增的部分无法析构

指针和引用的区别

1.指针保存的是指向对象的地址,引用相当于变量的别名。

2.引用必须被初始化,指针不一定被初始化。

3.指针可以改变地址,引用不能改变。

4.不存在空引用,但是可以存在空指针。

new/delete和malloc/free的区别

1.new是运算符,malloc是C语言库函数

2.new可以重载,malloc不可以重载

3.new的变量是数据类型,malloc的变量是空间大小

4.new自动调用构造函数,delete自动调用析构函数,malloc和free不可以。

5.new返回指向对象的指针,malloc返回void*,所以malloc的返回值需要进行类型转换。

6.malloc可以使用realloc扩容,new没有这样的操作。

7.new内存分配失败抛出bad_malloc,malloc内存分配失败返回NULL。

static关键词

1.对于普通全局或者局部变量,表示其在离开这个作用域之后就不可被访问了。

2.静态函数:在返回值类型之前加,只能在声明的文件内可见。

3.在类中的静态成员必须被初始化,这个静态成员被这个类的所有成员公有,且只有一份。

4.类的静态成员函数,表示这个函数是该类的范畴内的全局函数,没有this指针,只能访问静态成员变量和静态成员函数。

image-20210414124847736

extern关键词

声明一个外部变量。

const关键词

constant-不变的。

const修饰普通类型变量,这个变量的值不允许被改变。

const修饰指针变量:

const int * p =8; 指针指向的内容 8 不可变。 p是一个指针指向const变量 int

int * const p =&a; 这个指针指向的内存地址不能被改变。 p是一个const变量指向int *

const int const *p=&a; 指针和指向的值都不能改变。

const参数传递和函数返回值

值传递const一般不用

传递指针为参数 int* const p可以防止p指针被意外篡改。

自定义类型的参数传递,减少构造函数的时间。

返回值

const修饰自定义类型返回值,这个值不能作为左值。

const 修饰返回的指针和引用,是否返回一个指向const的指针。

修饰成员函数

int get_cm()const 这个函数不可以修改成员值

define 和inline

define的本质是字符串替换

inline是由编译器控制的。

inline在编译时展开,宏是预处理器对宏展开。

内联函数检查参数类型,宏不检查。

宏不是函数,inline是函数

宏在定义时要小心处理宏函数

image-20210414132358594

C++11新特性(智能指针、lambda、range)

lambda匿名函数

[函数对象参数] (操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void show(vector<int>&my,void(*func)(int))
{
    for(auto i:my)
        func(i);
}
int main()
{
    vector<int> my{1, 2, 3, 4, 5};
    show(my, [](int value) { cout << "value:" << value << endl; });
}

智能指针

野指针:没有被初始化的指针

悬空指针:初始化的但是指向的对象已经不在了的指针

智能指针有auto_ptr,unique_ptr,shared_ptr,weak_ptr

auto_ptr已经在c++11被删除

智能指针主要用于管理在堆上分配的内存,它将普通指针封装为对象,当对象的生命周期结束之后会调用析构函数释放掉内存,防止悬空指针的出现(内存泄漏)。

auto_ptr 采用所有权模式

auto_ptr<string> p1 (new string ("I reigned lonely as a cloud.")); 
auto_ptr<string> p2; 
p2 = p1; //auto_ptr不会报错.

p2剥夺的p1的所有权,程序访问p1的时候报错。

unique_ptr 独占式

保证同一时间只能有一个指针访问这个对象

shared_ptr 共享式独有概念

多个智能指针可以指向同一个对象,对象和资源会在最后一个引用被销毁之后释放,通过计数机制表明被多少个指针共享

存在问题:当两个对象相互使用一个shared_ptr指向对方,会造成循环引用,引发计数失效,导致内存泄漏。

weak_ptr 一个智能指针协助shared_ptr工作,这种指针不会增加对象的引用计数

#include <iostream>
#include <vector>
#include <algorithm>
#include<string>
#include<memory>
using namespace std;
int main()
{
    shared_ptr<int> p1(new int);
    weak_ptr<int> p2;
    p2 = p1;
    cout << p1.use_count()<<endl;
    shared_ptr<int> p3;
    p3 = p1;
    cout << p1.use_count();
}

字节对齐

变量存储的起始位置是该变量大小的整数倍

结构体总的大小是最大元素的整数倍

空结构体sizeof()是1

静态链接和动态链接

静态链接是在编译链接时候将需要的代码拷贝到调用处,优点是发布的时候不需要依赖库,但是体积会更大一点

动态链接是在编译的时候不直接拷贝可执行代码,记录一系列符号函数,在运行或者加载的时候再把这些传入操作系统,操作系统负责将动态库加载到内存中,程序运行到对应代码的时候,共享执行内存中已经加载的动态库的可执行代码达到运行时连接的目的。有点是多个程序可以共享一段代码。

抽象类

如何让一个类不能实例化:将类定义为模板类或者把构造函数声明在private

如何创建一个类只能在堆和栈上创建

只能在堆上生成对象:将析构函数设置为私有。
原因:C++是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。

只能在栈上生成对象:将new 和 delete 重载为私有。
原因:在堆上生成对象,使用new关键词操作,其过程分为两阶段:第一阶段,使用new在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。将new操作设置为私有,那么第一阶段就无法完成,就不能够再堆上生成对象。

template

template <typename type> ret-type func-name(parameter list)
{
   // 函数的主体
}

template实现swap

#include<iostream>
#include<string>
#include<vector>
using namespace std;
template <typename T> void swat (T&a,T&b)
{
    T temp = a;
    a = b;
    b = temp;
}
int main()
{
    int a = 1;
    int b = 2;
    double c = 0.1;
    double d = 0.2;
    swat(a, b);
    swat(c, d);
    cout << a << " " << c;
}

template实现冒泡(如果面试让你写冒泡最好用template可以表现自己)

#include<iostream>
#include<string>
#include<vector>
using namespace std;
template<typename T> void swp(T&a,T&b)
{
    T temp = a;
    a = b;
    b = temp;
}
template <typename T>
void get(T*a,int len)
{
    for (int i = 0; i < len;i++)
        cin >> a[i];
}
template <typename T>
void srt(T *a,int len)
{
    for (int i = 0; i < len;i++)
    {
        for (int j = 0; j < len - 1 - i;j++)
        {
            if(a[j]>a[j+1])
                swp(a[j], a[j + 1]);
        }
    }
}
template <typename T>
void print(T*a,int len)
{
    for (int i = 0; i < len;i++)
        cout << a[i] << " ";
}
int main()
{
    char t[8];
    int len = 8;
    get(t, len);
    srt(t, len);
    print(t, len);
}
posted @ 2021-04-14 14:27  NodMouse  阅读(250)  评论(0)    收藏  举报