目录
一、堆和栈的区别
特性 | 堆 | 栈 |
---|---|---|
申请方式 | 由程序员显式申请和释放 | 由系统自动分配和释放 |
分配方式 | 动态分配 | 自动分配 |
分配效率 | 相对较慢,需要遍历内存链表寻找合适空间 | 相对较快,系统直接分配 |
内存地址 | 不连续的内存区域 | 连续的内存区域 |
大小限制 | 大小灵活,上限取决于虚拟内存 | 大小固定,通常较小 |
内存碎片 | 容易产生内存碎片 | 不易产生内存碎片(栈是后进先出) |
生长方向 | 向上扩展 | 向下扩展 |
访问速度 | 相对较慢,需要两次访问(指针和地址) | 相对较快,直接访问 |
默认值 | 无默认值,需要程序员显式初始化 | 在定义时自动初始化 |
使用场景 | 大对象、动态数据结构、需要长时间保存的数据 | 局部变量、函数调用、小对象 |
二、 C++中new、delte和malloc的区别
特性 | new/delete | malloc |
---|---|---|
所属 | C++运算符 | C/C++库函数 |
分配内存 | 是 | 是 |
释放内存 | 是 | 是 |
调用构造函数/析构函数 | 是 | 否 |
类型安全 | 是 | 否 |
支持重载 | 是 | 否 |
支持覆盖 | 否 | 是 |
效率 | 相对较高(直接调用) | 相对较低(需要函数调用) |
返回值类型 | 具体类型指针 | void类型指针 |
内存分配方式 | 自动计算所需大小 | 手动计算所需大小 |
三、什么是源对象
C++ 中的源对象(source object)是指在进行对象复制或对象移动操作时,被复制或移动的对象。在 C++ 中,对象的复制和移动操作是通过拷贝构造函数和移动构造函数来完成的。
当使用拷贝构造函数进行对象复制时,源对象的内容会被复制到新创建的对象中。拷贝构造函数通常使用const
引用参数来引用源对象,以确保源对象的内容不会被修改。例如:
class MyClass {
public:
MyClass(const MyClass& other) {
// 复制源对象的内容
this->member1 = other.member1;
this->member2 = other.member2;
}
private:
int member1;
int member2;
};
MyClass obj1;
MyClass obj2 = obj1; // 使用拷贝构造函数复制对象
obj1
是源对象,obj2
是通过拷贝构造函数创建的新对象,它是obj1
的副本。
自己的理解:在 C++ 中,源对象就像一个原版的玩具,它有自己的属性和行为。当我们想要制作一个玩具的副本时,我们可以使用拷贝构造函数,就像用复印机复制一份原版玩具一样。这样,我们就得到了一个和源对象完全一样的副本。
四、C++有哪些设计模式
设计模式之间的区别主要体现在它们的应用场景、解决的问题和实现方式上。以下是一些常见的设计模式及其主要区别:
-
单例模式:确保一个类只有一个实例,并且这个实例向整个系统提供功能。它通常用于管理那些只需要一个实例的资源,例如配置信息或线程池。
-
访问者模式:对于数据结构相对未确定的系统,它将数据结构和基于数据结构的操作解耦合,让操作集合可以自由演化。这种模式适用于那些需要增加新的操作但不想修改原有类的情况。
-
桥接模式:将抽象化与实现化脱离,使得二者可以独立的变化。它主要用于处理那些需要在抽象和具体实现之间建立灵活关联的场景。
-
适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。这种模式常用于解决接口不兼容的问题。
-
合成模式:将对象组织到树结构中,用来描述整体与部分的关系。它适用于那些需要表示部分与整体层次结构的场景。
-
解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。它主要用于构建解析器或解释器,用于处理特定的语言或规则。
五,你使用过C++哪些类型的指针
以下是一些常见的C++指针类型:
- 原始指针(Raw Pointers):
- 这是最常见的指针类型,用于存储内存地址。
- 可以指向任何数据类型的对象,包括基本类型、结构体、类对象等。
- 需要手动管理其生命周期,以避免内存泄漏或悬挂指针。
- 智能指针(Smart Pointers):
- C++11引入了智能指针,用于自动管理内存生命周期,减少内存泄漏的风险。
- 包括
std::unique_ptr
、std::shared_ptr
、std::weak_ptr
和std::auto_ptr
(已被弃用)。 std::unique_ptr
:拥有其所指向的对象,同一时间只能有一个unique_ptr
指向给定对象(独占所有权的智能指针)。std::shared_ptr
:允许多个shared_ptr
实例指向同一个对象,通过引用计数来自动删除所指向的对象(共享所有权的智能指针)。std::weak_ptr
:是对shared_ptr
所管理的对象的一个非拥有性引用,它指向一个由shared_ptr
管理的对象,但不控制该对象的生命周期(观察共享所有权的智能指针)。
- 函数指针:
- 用于指向函数,可以通过函数指针调用函数。
- 通常用于回调函数、函数表等场景。
- 指针的指针(Pointer to Pointer):
- 指向指针的指针,常用于动态数组、二维数组或需要间接访问指针的场景。
- 空指针(Null Pointer):
- 不指向任何对象的指针,通常初始化为
nullptr
或NULL
。 - 用于表示指针没有指向任何有效的内存地址。
- 不指向任何对象的指针,通常初始化为
- 野指针(Wild Pointer):
- 指向已经被释放的内存的指针,是一种错误的指针使用方式。
- 使用野指针会导致不可预测的行为,应尽量避免。
- 悬挂指针(Dangling Pointer):
- 指向已经被释放或重新分配的内存的指针。
- 和野指针一样,悬挂指针也是危险的,应避免使用。
- 常量指针(Pointer to Const)和指向常量的指针(Const Pointer):
- 常量指针是指向常量的指针,不能通过该指针修改所指向的值。
- 指向常量的指针本身可以被修改以指向其他地址,但不能通过它修改所指向的值