C++八股

server/2024/9/23 2:21:43/

右值引用的应用与优点

  • 应用

    • 右值引用用于实现移动语义,避免不必要的数据复制。它特别适合于处理临时对象和大型资源管理(如动态分配内存、文件句柄等)。
    • 使用右值引用的主要场景是在自定义类的移动构造函数和移动赋值运算符中。
  • 优点

    • 性能提升:通过移动资源而不是拷贝资源,减少了内存分配和数据复制的开销。
    • 支持完美转发:结合std::forward可以在模板中实现参数的完美转发,从而保持传入参数的值类别。
    • 简化资源管理:右值引用使得编写高效的资源管理类变得更加容易,比如实现一个自定义的容器或智能指针。

Lambda表达式

  • 定义:Lambda表达式是一种能够定义匿名函数对象的方式,可以用来捕获外部变量并形成闭包。

  • 基本语法

    [capture](parameters) -> return_type {// function body
    }
    
    • 示例:
    auto add = [](int a, int b) { return a + b; };
    
  • 用途

    • 常用于 STL 算法,如std::sortstd::for_each等。
    • 用作回调函数,提高代码的可读性和简洁性。

空类的占用的内存

  • 在C++中,一个空类至少占用1个字节的内存。这是为了确保每个对象都有独特的地址,即便它不包含任何数据成员。这也符合C++标准中定义的对象大小至少为1字节的要求。

结构体的占用的字节数

  • 和类一样,C++中的结构体默认占用至少1个字节,其实际占用的字节数会因对齐和填充的需要而有所不同。如果结构体中有成员,则其大小为所有成员大小之和加上可能的填充字节。

虚函数与虚表

  • 虚函数:允许子类重写父类的方法,实现多态。只有当基类中定义了虚函数,派生类才能重写该函数。

  • 虚表:每个含有虚函数的类都有一个虚表(vtable),其中存储着指向该类的虚函数的指针。每个类的实例有一个指向该虚表的指针(即虚指针 vptr),用于在运行时确定调用哪个函数。

虚析构函数的作用

  • 作用
    • 当通过基类指针删除派生类对象时,如果基类的析构函数不是虚的,那么只会调用基类的析构函数,这可能导致派生类的资源没有被释放,产生内存泄漏。
    • 使用虚析构函数可以确保当删除基类指针指向的派生类对象时,会正确地调用派生类的析构函数,从而释放派生类所占用的资源。

传值和传址,深复制和浅复制

  • 传值

    • 将对象的副本传递给函数。在此情况下,函数内部对参数的修改不会影响原对象。
  • 传址

    • 传递对象的地址(指针或引用),允许函数直接操作原对象,函数内部的修改会影响原对象。
  • 深复制

    • 复制对象及其指向的动态分配内存,确保两个对象之间完全独立。通常在类中实现自定义的拷贝构造函数和赋值运算符。
  • 浅复制

    • 只复制对象的基本信息,指向同一块内存。当一个对象被修改或析构时,另一个对象也可能受到影响,导致未定义行为或资源冲突。

以下是有关C++的一些面试问题的详细回答:

前置++和后置++的本质区别与原理

  • 前置++ (++i)

    • 操作:首先将 i 的值增加1,然后返回 i 的新值。
    • 原理:直接在原对象上进行操作,通常通过引用或指针返回。
  • 后置++ (i++)

    • 操作:首先返回 i 的当前值,然后将 i 的值增加1。
    • 原理:为了实现这个功能,后置++ 通常会创建一个临时对象来保存原始值,返回该对象,并在完成后再增加 i 的值。
  • 总结

    • 前置++更高效,因为它不需要创建临时对象,而后置++则需要额外的内存开销。

map与set的原理及其他容器

  • map

    • 通常实现为红黑树(平衡二叉搜索树),存储键值对,提供O(log n)的查找、插入和删除性能。
    • 关键特点:每个键唯一,自动排序。
  • set

    • 类似于map,但只存储唯一的元素,通常也是基于红黑树实现。
    • 提供O(log n)的查找、插入和删除,且元素自动排序。
  • 其他容器

    • vector:动态数组,支持随机访问,增长时可能涉及内存重新分配。
    • deque:双端队列,支持两端插入和删除。
    • list:双向链表,支持快速插入和删除,但不支持随机访问。

C++内存空间划分,值类型和引用类型,C#的垃圾回收原理

  • 内存空间划分

    • :用于动态分配的内存,通过newdelete管理。
    • :用于局部变量的存储,自动管理内存的分配和释放。
    • 全局/静态存储区:存放全局变量和静态变量,程序运行期间存在。
    • 常量存储区、代码区。
  • 值类型和引用类型

    • 值类型:直接存储数据,例如基本数据类型(int, char等)和结构体。
    • 引用类型:存储对数据的引用,如指针和引用。对引用类型的修改会影响原始对象。
  • C#的垃圾回收原理

    • C#的垃圾回收(GC)自动管理堆上的内存,通过可达性分析算法确定哪些对象不再被使用,并回收它们占用的内存。GC使用代际假说来优化性能,优先回收较年轻代中的对象。这一机制减少了内存泄漏的风险,并简化了内存管理。

new与delete的本质及与malloc和free的区别

  • new

    • 在堆上分配内存,同时调用构造函数。
    • 示例:MyClass* obj = new MyClass();
  • delete

    • 调用析构函数并释放内存。
    • 示例:delete obj;
  • malloc

    • 仅申请指定大小的内存,不调用构造函数。
    • 示例:void* ptr = malloc(sizeof(MyClass));
  • free

    • 仅释放内存,不调用析构函数。
    • 示例:free(ptr);
  • 区别总结

    • newdelete是C++运算符,可以自动调用构造/析构函数;而mallocfree是C标准库函数,仅负责内存分配和释放,不处理对象生命周期。

内存泄漏的原因及避免方法

  • 造成原因

    • 动态分配内存但未及时释放,例如忘记调用deletefree,造成程序占用内存逐渐增大。
  • 避免方法

    • 使用智能指针(如std::unique_ptrstd::shared_ptr)自动管理资源的生命周期,确保在超出作用域时自动释放内存。
    • 定期检查代码中是否存在动态分配的内存未释放的情况,可以使用工具如Valgrind进行内存使用分析。

以下是针对C++面试问题的详细回答:

智能指针有哪些

C++11引入了几种智能指针,主要包括:

  1. std::unique_ptr

    • 独占式智能指针,每个指针只能由一个unique_ptr拥有,不能被复制,可以通过std::move进行转移。
    • 会自动在指针超出作用域时释放内存。
  2. std::shared_ptr

    • 共享式智能指针,允许多个shared_ptr共享同一块内存。使用引用计数管理资源的生命周期,当最后一个shared_ptr被销毁时,内存才会释放。
  3. std::weak_ptr

    • 弱引用智能指针,与shared_ptr配合使用,不增加引用计数,防止循环引用的问题。可以从一个shared_ptr获得,其目的在于观察而不控制对象的生命周期。

动态链接库和静态链接库的区别

  • 静态链接库(Static Library)

    • 在编译时将库的代码直接与应用程序的代码连接到一起。生成的可执行文件(.exe)包含所有必要的库代码。
    • 优点:无需依赖外部库文件,部署过程简单。
    • 缺点:可执行文件体积较大,更新库时需重新编译应用程序。
  • 动态链接库(Dynamic Link Library, DLL)

    • 在运行时加载,程序可以在运行时调用DLL中的函数。DLL文件与可执行文件分开,多个应用可以共享同一个DLL。
    • 优点:可减小可执行文件体积,便于版本更新和共享。
    • 缺点:需确保DLL文件存在且版本兼容。
  • 关于EXE与链接

    • 一般情况下,生成的.exe文件是静态链接的,而.dll文件是动态链接的。这意味着EXE在编译时已将所需的库代码集成,但在运行时可能仍然可以调用动态库。

二维指针

  • 二维指针通常表示一个指向指针的指针,例如:int **p 可以用来表示一个二维数组或数组的数组。
  • 实际上,二维指针在内存中是一个指向指针数组的指针,每个指针又指向一个具体的行数据。
int rows = 5;
int cols = 4;
int **array = new int*[rows]; // 创建一维指针数组,用于指向每行
for (int i = 0; i < rows; i++) {array[i] = new int[cols]; // 为每行分配列数
}
// 使用完后记得释放内存
for (int i = 0; i < rows; i++) {delete[] array[i];
}
delete[] array;

指针和引用的区别

  1. 定义方式

    • 指针使用*符号定义,如int *ptr;
    • 引用则使用&符号定义,如int &ref = var;
  2. 空值

    • 指针可以为nullptr或指向某个有效地址。
    • 引用必须在初始化时绑定到某个对象,不能为null。
  3. 重新赋值

    • 指针可以重新赋值,指向不同的对象。
    • 引用一旦绑定到某个对象后就不可改变,如要改变需要使用新的引用。
  4. 语法

    • 使用指针时需要解引用操作符*,如*ptr
    • 使用引用时不需要解引用,直接使用引用名即可。

宏定义,常见的宏指令

  1. #define

    • 定义宏常量或宏函数。例如:#define PI 3.14#define SQUARE(x) ((x)*(x))
  2. #ifdef / #ifndef

    • 用于条件编译,即根据是否定义了某个宏来决定是否编译某段代码。
    • 例如:
      #ifdef DEBUG
      std::cout << "Debug mode" << std::endl;
      #endif
      
  3. #if / #else / #elif

    • 也是用于条件编译,根据表达式的值来选择编译哪部分代码。
  4. #include

    • 引入头文件
  5. #undef

    • 用于取消之前定义的宏。例如:#undef PI 取消对 PI 的定义。
  6. #pragma

    • 用于向编译器发送特殊指令,可以控制编译器的某些行为,如警告等级、优化选项等。例如:
      #pragma once // 防止头文件被多次包含
      
  7. #line

    • 用于改变编译器报告的行号和文件名,主要用于调试目的。
  8. #error

    • 触发编译错误,可以在特定条件下提示开发者。例如:
      #ifdef DEBUG
      #error "Debug mode is enabled!"
      #endif
      

null 与 nullptr 的区别

  • null

    • null 是一个常量,通常用于表示空指针。在 C++ 中,null 实际上是一个宏,代表整数常量 0。使用 null 时可能会引发类型不明确的问题,因为它可以隐式转换为任何指针类型。
  • nullptr

    • C++11 引入的新关键字,用于表示空指针。与 null 不同的是,nullptr 是一个类型安全的指针常量,不能隐式转换为整数或其他类型。这使得在函数重载中更清晰,加上 nullptr 使得代码在处理空指针时更加安全。
int* p1 = nullptr; // 正确
int* p2 = null;    // 在C++标准中,推荐使用nullptr,null可能会导致警告

http://www.ppmy.cn/server/114782.html

相关文章

JVM系列(八) -运行期的几种优化技术

一、摘要 在之前的文章中我们谈到过,相比 C/C++ 语言,Java 语言在运行效率方面要稍逊一些,因为 Java 应用程序是在虚拟机上运行,而 C/C++ 程序是直接编译成平台相应的机器码来运行程序。 从虚拟机对外发布开始,开发团队一直在努力试图缩小 Java 与 C/C++ 语言在运行效率…

怎样给U盘加密?看这里!30s学会四种方法,保护你的数据安全!

在一家中型科技公司里&#xff0c;一名员工将包含重要项目资料的U盘遗忘在咖啡店的桌子上。该U盘内存有公司尚未公开的新产品设计图纸、客户信息以及财务报告等敏感数据。几小时后&#xff0c;这个未加密的U盘被一名陌生人拾到并插入其电脑中查看&#xff0c;机密信息被上传到网…

【网络】DNS协议、ICMP协议

DNS协议与ICMP协议 文章目录 1.DNS协议1.1DNS背景1.2域名简介1.3域名解析过程&#xff08;了解&#xff09;1.4使用dig工具分析DNS过程 2.ICMP协议2.1ICMP的功能2.2ping命令2.3traceroute命令 1.DNS协议 DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;协…

Servlet 和 Spring Boot 的请求处理流程区别和例子

当然可以为您绘制一个流程图&#xff0c;展示 Servlet 和 Spring Boot 的请求处理流程。这将帮助我们更直观地比较两者的工作方式。 #mermaid-svg-PgFEmecUmDhvxxtQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-P…

《生物学教学》

《生物学教学》杂志是由国家教育部主管、华东师范大学主办&#xff0c;向国内外正式发行的全国教育类核心期刊。主要栏目有&#xff1a;生物科学综述、课程标准与教材、当代教育论坛、国外教育动态、教师教育、教育教学研究、教学设计案例、信息技术、考试与评价、实验教学、探…

Docker 的安装和使用

参考资料&#xff1a; 通俗易懂了解什么是docker?Docker 教程 | 菜鸟教程Ubuntu 22.04 安装 DockerDocker 超详细基础教程WSL2 支持 systemctl 命令systemd 和 systemctl 是什么&#xff1f;使用正确的命令重启 WSL 子系统Ubuntu 修改源镜像方法Docker 中出现 ‘/etc/resolv.…

vue2关闭eslint

vue2关闭eslint 1、找到项目build目录下的webpack.base.conf.js文件 2、注释createLintingRule()里面的内容&#xff08;只注释里面的内容&#xff09; 3、重启项目即可

大语言模型的上下文窗口(Context Windows):对人工智能应用的影响

大语言模型&#xff08;LLMs&#xff09;极大地提升了人工智能在理解和生成类人文本方面的能力。其中一个影响其效用的基本方面是它们的 “上下文窗口”—— 这个概念直接影响着这些模型接收和生成语言的有效性。我将深入探讨上下文窗口是什么、它们对人工智能应用的影响以及组…