C++常见问题

1.const关键字

Const修饰的成员方法访问成员变量只能够读取成员变量不能够修改(但是能过够修改static成员变量),修饰的方式是:

 数据类型 函数名() const{}

 

2.引用

C++的引用相当于取别名。定义时用到了取地址符号,打印值的时候不需要取地址符号。如果取别名对象的值改变,引用的值也响应的改变。

3.函数重载

C++允许用同一函数名定义多个函数,是C++中多态性的一种形式,它允许在一个作用域内定义多个同名函数,只要这些函数的参数列表不同即可(作用区域相同,不关心返回值,看参数的个数和类型)。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。

 

4.默认传参

若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须也设置默认值

在调用时,若给已经设置默认值的参数传递实际值,既要取代默认值,则在参数表中被取代

参数的左边所定义的所有参数,无论是否有默认值,都必须传递实际参数

 

5.作用域和名字空间

作用域:局部域,名字空间域,类域。变量域(局部变量,全局变量,静态变量),函数域不能是局部域。

名字空间:

在C++中,命名空间(namespace)是一种用于组织代码的机制,它可以帮助解决命名冲突问题,使得不同模块或库中的标识符(如变量、函数、类等)可以使用相同的名称而不会相互干扰。不同的类可以使用相同的名称。可以使用 using namespace 指令将整个名字空间引入到当前作用域中。

 

6.c++链接性

简单说一下c++的链接性?

外部链接:标识符可以在多个编译单元之间共享。全局变量和非内联的非静态函数通常具有外部链接。

内部链接:标识符仅在声明它们的编译单元内可见。使用 static 关键字声明的全局变量和函数具有内部链接。

无链接:标识符仅在声明它们的作用域内可见。局部变量和类内的静态成员变量具有无链接

 

7.构造和析构函数

构造函数:函数名和类名相同,且不能自定义,无返回值,可以有0-n个参数,当定义对象的时候,自动调用

析构函数:(当对象即将消亡的时,释放资源 )

 函数名和类名相同,不能自定义,在前面加 ~ , 无参, 无返回值,

Explict的限制构造函数:explicit 修饰,因此不能进行隐式构造和隐式类型转换

MyClass obj1(10); // 显式构造// MyClass obj2 = 20; // 错误:隐式构造被禁止  

 // 隐式类型转换  // MyClass obj3 = 30 + 10;

MyClass obj1(10); // 显式构造
MyClass obj2 = 20; // 错误:隐式构造被禁止  
MyClass obj3 = 30 + 10;// 隐式类型转换  

8.浅拷贝和深拷贝

浅拷贝(Shallow Copy)

浅拷贝是指在拷贝对象时,仅仅复制对象中的值类型成员,对于指针成员,只是复制指针本身,而不是指针所指向的数据。这意味着两个对象的指针成员将指向同一个内存地址。

深拷贝(Deep Copy)

深拷贝是指在拷贝对象时,不仅复制对象中的值类型成员,还为指针成员分配新的内存,并将指针所指向的数据复制到新的内存中。这意味着两个对象的指针成员将指向不同的内存地址。

 

9.什么是内存泄露?如何检查?如何防止?

什么是内存泄露:我们的程序除了用到静态内存和栈内存,每个程序还拥有一个内存池,我们把他叫做自由空间或者堆。
在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化:delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。 
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时 
我们会忘记释放内存,在这种情况下就会产生内存泄漏;

1)使用 IDE 提供的调试工具跟踪调试,并在软件窗口中监视内存的使用情况;这种方式比较慢,常与

断点配合使用,检查部分代码段有效;

2)使用 glibc 库的内置函数 mtrace()/muntrace()来检测可能出现内存的漏的代码段;

3)安装 Valgrind Memcheck 是检测工具(Linux 下一款程序),使用如下命令执行代码即可:

valgrind --tool=memcheck --leak-check=full --log-file=./log.txt ./a.out

  1. 还有一些检测内存泄露的函数库/工具,如:dmalloc(动态库)、memwatch(动态库)、 mpatrol

防止方法:

1)在C++中智能指针可以做到堆对象自动释放,

这能有效避免内存泄露;

2)使用托管类接管堆对象(锁管理就是一个例子),避免异常中断导致灾难性的资源泄露;

3)能使用栈对象就不要使用堆对象,避免忘记释放堆对象(这个不报错,但有隐患);

 

10.MVC模型,分别指的是哪个单词的缩写,分别代表什么意思?

M model模型,v view视图 c controller控制器

含义:模型负责管理和处理应用程序的数据逻辑。它与数据源(如数据库、文件等)交互,获取和存储数据。模型不关心数据的展示方式,只关注数据的结构和逻辑。 

含义:视图负责展示数据给用户。它是用户界面的一部分,用于呈现模型中的数据。视图不直接处理数据,也不执行业务逻辑,它只是显示数据。

含义:控制器是模型和视图之间的桥梁。它接收用户的输入,处理用户请求,并更新模型或视图。控制器负责协调模型和视图的交互。

 

11.指针和引用的区别

1.指针可以初始化为NULL,或者不初始化为随机值。引用必须初始化

2.指针的优点是灵活,可以操作连续内存空间;缺点是容易导致越界和内存溢出 的问题。

引用的优点是安全,不用传参相当于取别名,可提高效率;缺点是不够灵活

 

12.new delete和malloc free的区别

new的时候调用构造函数可以传递数据,报错可以抛出异常throw。Malloc只能动态开辟自由内存,空间内没有数据,通过返回值知道成功与否。

2)delete 释放的空间不可再使用,一旦

使用直接报错。

free()释放的空间是不可继续使用,但意外使用的话不会报任何错误,只是数据不确定。

 

13.什么是高内聚低耦合

内部实现很复杂,外部调用接口很简单

增强内聚:1)多用private少用public 2)两个类能合成一个类尽量合

减少耦合:1)少用继承多用成员方法(接口) 2)局部定义,少用全局变量

 

 

14.(多重继承,虚继承,菱形继)c++对象的内存布局。构造顺序

有虚函数的类都有虚函数表,虚函数表存放虚函数的地址。

使用虚继承可以解决基类被多次实例化的问题,确保基类只有一个实例。

多重继承:基类的构造函数按声明顺序调用,派生类的构造函数最后调用。

虚继承:虚基类的构造函数首先调用,非虚基类的构造函数按声明顺序调用,派生类的构造函数最后调用。

虚析构函数的作用: Base* basePtr = new Derived();

    basePtr->show();  // 调用 Derived 的 show 方法

delete basePtr;   // 通过基类指针删除派生类对象

举例一个基类指针指向派生类对象(也是多态的实现),删除基类指针时,不仅会删除基类的析构函数,派生类的析构函数也会被调用。

 

15.STL标准函数库有哪些

容器、算法、迭代器、函数对象(仿函数)、适配器(配接器)、内存分配器(空间配置器)

常见STL容器:

Vector list deque  map set

16.重载覆盖隐藏

重载:在同一作用域内,函数名相同,但参数列表不同(参数个数、类型或顺序不同)。

覆盖:在派生类中,重写基类中的虚函数(virtual 函数),函数名相同,参数列表相同,返回类型相同(或协变)。(必须在基类中声明为 virtual

隐藏:在派生类中,定义了一个与基类中同名的函数,但参数列表不同;或者基类中的函数是虚函数而派生类中的函数是虚函数或者非虚函数(2*2 11和10是覆盖,00和01是隐藏)

覆盖有动态绑定,隐藏没有:动态绑定:通过基类指针调用派生类同名方法时,编译器会生成代码来查找虚函数表(vtable),并根据虚函数表中的指针调用相应的函数实现。(根据实际对象的类型来决定调用哪个方法)

虚函数的性质:在C++中,如果基类中的函数是虚函数,那么派生类中的同名函数(即使没有显式声明为 virtual)也会被视为虚函数,并且会覆盖基类中的虚函数。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值