八股总结-----C++、数据结构、算法

1.内存基础

11.内存分区

代码区:存储可执行代码(程序指令)。

全局区:存储全局变量和静态变量(已初始化和未初始化)。

堆区:用于动态内存分配,由程序员管理。

栈区:存储函数调用中的局部数据(局部变量、参数、返回地址)。

12.堆和栈有什么区别

堆和栈是用来内存分配和释放的两种不同的内存区域,内存管理就是内存分配和释放。栈的存储空间比较小,用于存储局部变量、函数参数、返回值,适合小数据结构的存储,内存分配和释放速度快,自动管理(自动分配、自动销毁)。堆的存储空间较大,用于动态内存分配,适合大型数据结构存储,内存分配和释放速度较慢,手动管理(malloc、new、free、delete)。

2.指针

21.智能指针

智能指针是C++标准库中的一种工具,用于自动管理动态内存,避免内存泄漏和指针悬挂问题。智能指针主要有以下几种类型:

1. std::unique_ptr

  • 独占所有权unique_ptr表示独占的所有权,即一个指针对象在任何时刻只有一个所有者。
  • 不可复制unique_ptr不能被复制,只有通过std::move转移所有权。
  • 场景:适合用于需要严格的所有权语义的场合,如资源管理。

2. std::shared_ptr

  • 共享所有权shared_ptr允许多个智能指针共享同一块内存。当最后一个shared_ptr释放时,内存才会被释放。
  • 引用计数:每个shared_ptr都有一个引用计数,用于记录有多少shared_ptr共享该内存块。
  • 场景:适用于需要在多个地方共享资源的情况。

3. std::weak_ptr

  • 弱引用weak_ptr不会影响引用计数,不能直接访问资源,需要先提升为shared_ptr
  • 防止循环引用:常用于打破shared_ptr之间的循环引用,避免内存泄漏。
  • 场景:适用于需要观察但不拥有资源的场景,如缓存或观察者模式中。

智能指针的作用

  • 自动内存管理:智能指针在离开作用域时自动释放资源,避免了手动释放内存的麻烦和错误。
  • 防止内存泄漏:通过智能指针的自动内存管理机制,减少了忘记释放内存导致的内存泄漏问题。
  • 简化代码:智能指针封装了内存管理细节,简化了资源管理的代码。

22.常量指针和指针常量有什么区别?

看const后面跟的什么,跟的int就是修饰数据,数据不可变,指针指向可变,称为指针变量const int *p。跟的p就是修饰指针,指针指向不可变,数据可变,称为变量指针int * const p。

23.define 和 const 的区别?

作用:用于记录程序中不可更改的数据
C++定义常量两种方式
1. #define 宏常量: #define 常量名 常量值
==通常在文件上方定义==,表示一个常量
2. const修饰的变量 const 数据类型 常量名 = 常量值
==通常在变量定义前加关键字const==,修饰该变量为常量,不可修改

24.static的作用

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员,可以通过对象和类名两种方式访问。静态成员分为:

静态成员变量:1.所有对象共享同一份数据;2.在编译阶段分配内存;3.类内声明,类外初始化;
静态成员函数:1.所有对象共享同一个函数;2.静态成员函数只能访问静态成员变量。(因为静态属于类,非静态属于对象 ,静态成员变量是由类调用的,不用区分是类中的哪个对象调用,但是非静态成员变量是由对象调用的,这时候用静态成员函数去调用非静态成员变量,无法区分到底是哪个对象调用的变量)

静态成员是指属于类本身而不是类的实例的成员。静态成员有以下意义:
共享性:静态成员被所有类的实例共享,可以在不创建类的实例的情况下访问和修改静态成员。
保存状态:静态成员可以用来保存类的状态信息,例如计数器、配置信息等,这些信息可被所有实例共享和访问。
简化访问:可以通过类名直接访问静态成员,无需创建类的实例。这样可以简化代码并提高代码的可读性。
与类相关联:静态成员通常与类本身相关联,而不是与类的实例相关联。这样可以更好地表达类的特性和行为。

3.虚函数

31.什么是虚函数?什么是纯虚函数?

  • 虚函数 用于在基类中声明,并允许在派生类中重写,以实现多态性。
  • 纯虚函数 是没有实现的虚函数,存在于抽象类中,必须在派生类中实现,否则派生类也将成为抽象类。纯虚函数常用于定义接口,强制派生类提供特定的功能。

析构函数可以是虚函数吗?

4.vector容器

std::vector 是 C++ 标准库中的动态数组,它会根据需要自动调整其容量以容纳更多的元素。std::vector 会在内部维护一个存储空间的容量(capacity),这个容量通常会大于或等于当前元素的数量(size)。当向 std::vector 中添加元素并且元素的数量超过当前容量时,vector 会重新分配更大的内存空间来容纳这些元素。这个过程包括:

  1. 分配新的内存块vector 会分配一个更大的内存块以容纳更多的元素。
  2. 复制现有元素:将旧内存块中的元素复制到新的内存块中。
  3. 释放旧内存块:释放旧的内存块以释放内存。

std::vector 的初始容量和扩容策略取决于具体的实现,但一般来说,std::vector 的初始容量为 0。也就是说,当你创建一个空的 vector 对象时,它通常没有分配任何内存用于存储元素。

初次扩容

std::vector 的初次扩容通常发生在以下几种情况:

  1. 添加元素:当你向一个空的 vector 中添加第一个元素时,vector 会进行初次扩容。此时,它会分配一个足够容纳至少一个元素的内存块。许多实现将初始容量设置为较小的值,比如 1 或 4,以提高性能。

  2. 构造函数:如果你使用特定构造函数创建 vector,比如 vector(size_type count, const T& value)vector(std::initializer_list<T> init)vector 会根据提供的初始元素数量预分配内存,以减少后续的扩容次数。

扩容策略

在添加更多元素并超过当前容量时,std::vector 会进行扩容。扩容通常遵循以下策略:

  • 容量增加:每次扩容时,vector 的容量通常会增加到当前容量的两倍,这样可以减少扩容的次数和内存分配的开销。(2倍策略通常在性能和内存利用之间提供了一个好的折衷)
  • 策略实现:不同的标准库实现可能会有不同的策略,但大多数都遵循类似的增量规则以确保高效的内存管理。

扩容过程中,std::vector 需要重新分配内存,复制现有元素到新的内存块中,并释放旧的内存块。这个过程是自动进行的,用户不需要手动处理。

5.介绍几种常用的排序算法

冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值