C++常见概念问题(3)

C++常见概念问题(3)

1. 构造函数的初始化顺序

基类构造函数:在派生类的构造函数中,基类的构造函数在派生类构造函数体执行之前调用。
成员变量初始化:类中的成员变量会按照其在类中声明的顺序进行初始化,而不是按照构造函数初始化列表中的顺序。

2. C++内存分区模型

C++分区模型 程序运行前,编译的时候:

代码区:存放函数体的二进制代码,由操作系统进行管理,特点(共享,可读)
全局区:存放全局变量静态变量以及常量,该区域的数据在程序结束后由操作系统释放

程序运行后:

栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收

3. 宏定义和全局变量的区别

  1. 数据类型
    宏定义:没有特定的数据类型,因为它仅仅是文本替换,编译器在预处理阶段进行替换,不占用内存。
    全局变量:有具体的数据类型(如整型、浮点型、字符串等),并占用相应的内存空间。
  2. 定义方式
    宏定义:使用预处理指令 #define 来定义,通常用来替代常量或表达式。例子:#define PI 3.14
    全局变量:定义在函数外部
  3. 作用域
    都可以在本文件使用。
    如果跨文件,可以加入extern 关键字在其他文件中使用。

4. 全局变量,静态变量,常量

4.1 全局变量

全局变量是定义在函数外面的变量,本文件内都可以访问。如果想跨文件访问,也可以使用extern关键字实现。

int globalVar = 42;

另一个文件

extern int globalVar;

全局变量在程序运行前的编译阶段就分配了内存,直到程序完全结束,由操作系统释放。

4.2 静态变量

  • 局部静态变量:给函数内部的局部变量加上关键字static,变成函数内部的静态变量,原本局部变量的生命周期随着函数结束。变成静态变量后,生命周期改变了,作用域没有改变。

    生命周期变得和全局变量一样,持续到程序结束。由操作系统释放。
    作用域没有改变,意味着别的函数还是无法访问这个局部静态变量,只有自己函数能访问。上次执行完这个函数,局部静态变量的值会被保存下来,下次再调用这个函数时,接着使用

  • 全局静态变量:那么给全局变量加上关键字static,相比于全局变量,全局静态变量有什么改变:首先生命周期没变,作用域变了,全局静态变量只能在本文件访问到,不能通过extern关键字跨文件访问。

为什么需要静态变量:

  1. 保持状态
    静态变量能够保存函数调用之间的状态。这意味着即使函数执行结束,该变量的值仍然可以被保留并在后续调用中继续使用。

  2. 共享数据
    在类或模块内部,静态变量可以被所有实例或调用共享。这样可以避免使用全局变量,同时又能跨多个实例共享数据,减少了命名冲突的风险。

  3. 内存管理
    静态变量通常在程序的整个生命周期内存在,不需要频繁地分配和释放内存。这对于性能敏感的应用尤为重要,因为它可以减少内存分配的开销。

  4. 初始化控制
    静态变量只会在第一次使用时进行初始化,这样可以确保其初始状态一致,并且在多次调用时不会重复初始化。

  5. 封装性
    使用静态变量可以隐藏实现细节,提供更好的封装性。从外部看,静态变量可以限制访问权限,使得数据的管理更加严谨。

4.3 常量

使用 const 关键字定义的不可修改的变量。
生命周期同样是编译时分配空间,程序结束时操作系统释放资源。
常量的作用域依赖于定义的位置,可以是全局的、局部的,或在类中定义。

函数重载的底层本质

核心:C++之所以有重载,其原因是函数名修饰规则不同

对于C语言,相同的函数名,其修饰名必然相同,与参数无关,因此不同参数的同名函数的修饰名是重复的,因此无法同时存在,更无法实现重载;

C++之所以能够实现重载,是因为编译器能够区分同名不同参的函数,而其区分的底层原理就是对原函数名进行修饰,或者叫重命名

编译前的重载函数(同名不同参的函数),编译后就是不同名的函数,这个新的函数名中不仅包含了原名,还包含了参数信息;

C++和C怎么协同开发(c++项目怎么引用c的文件)

假如在c++文件中使用C的源文件example.c

// example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H

#ifdef __cplusplus
extern "C" {
#endif

void c_function();

#ifdef __cplusplus
}
#endif

#endif // EXAMPLE_H


#ifndef EXAMPLE_H
头文件保护(Include Guard): #ifndef 是 "if not defined" 的缩写。这条指令检查宏 EXAMPLE_H 是否未被定义。如果没有被定义,则继续执行后面的代码;如果已经定义,编译器将跳过这个头文件的内容,以避免重复包含同一头文件造成的潜在错误。
#define EXAMPLE_H
定义宏: 如果上面的条件成立,这里会定义宏 EXAMPLE_H。这意味着在后续的编译过程中,如果再出现 #ifndef EXAMPLE_H,条件将不再成立,从而避免了重复包含该头文件。
#ifdef __cplusplus
检查 C++ 编译器: #ifdef 指令用于检查是否在 C++ 编译环境下编译。如果 __cplusplus 宏已定义,这表示当前正在使用 C++ 编译器。
extern "C" {
防止名称修饰: extern "C" 告诉 C++ 编译器以 C 的方式链接函数。在 C++ 中,为了支持函数重载,编译器会对函数名进行“名称修饰”。使用 extern "C" 可以避免这种情况,使得 C 函数可以在 C++ 中被正确调用。
void c_function();
函数声明: 这里声明了一个名为 c_function 的函数,其返回类型为 void,表示此函数不返回任何值。同时,没有参数列表,表示该函数接受任何数量和类型的参数。
#ifdef __cplusplus
结束 C++ 检查: 这一行与之前的 #ifdef __cplusplus 相对应,用于结束对 C++ 编译环境的检查。
}
结束 extern "C": 这个括号标志着 extern "C" 块的结束,表示在这个块内的所有函数声明都应按照 C 的方式处理,而不是 C++ 的标准方式。
#endif // EXAMPLE_H
结束头文件保护: 这一行对应于前面开始的 #ifndef EXAMPLE_H,它结束了头文件保护的定义。任何在这个保护区块内的代码都会被保证只会被编译一次。

c++迭代器,和迭代器失效的原因

定义: 迭代器类似于指针,它们指向容器中的某个元素,并且能够在容器中前后移动。通过迭代器,可以读取和修改容器中的数据。

迭代器类似于指针,它们指向容器中的某个元素,并且能够在容器中前后移动。通过迭代器,可以读取和修改容器中的数据。

迭代器失效的原因

容器大小变化:

插入(Insert): 如果在迭代器当前位置插入元素,可能会导致所有指向该位置及之后元素的迭代器失效。
删除(Erase): 删除迭代器指向的元素会使该迭代器失效,通常还会影响其他迭代器(例如,删除某个位置之前的元素会使之后的迭代器失效)。
调整容器大小: 对于动态大小的容器(如 std::vector),如果超过了其容量,可能会重新分配内存,这会使所有指向旧内存的迭代器失效。

容器清空:
调用 clear() 函数清空容器时,所有与该容器相关的迭代器都会失效。
直接赋值或重新初始化:

例如,将一个容器赋值给另一个新容器后,之前的迭代器指向的内容可能会失效。

resize和reserve方法

resize()
resize 会 改变容器的大小。它的作用是调整容器的当前大小,即容器内元素的个数。
如果新大小大于当前大小:会增加容器的元素数量,并且这些新增的元素会根据容器的类型进行默认初始化。例如,对std::vector,新增加的元素将会是 0。
如果新大小小于当前大小:会删除容器中的多余元素,容器的大小会减少。

reserve()
reserve 不会改变容器的大小,它只是调整容器的 容量(capacity),即指定一个容器最大容量。
如果目前内存能够放下这个最大容量的数据结构,没变化。
如果目前内存放不下最大容量的数据结构,扩容为指定容量的内存大小。

使用reserve 主要是为了优化性能,避免在插入新元素时频繁重新分配内存
假设 std::vector 中的每个元素占据 4 字节(在大多数平台和编译器中,int 通常是 4 字节),那么在调用 reserve(100) 后,std::vector 会为 100 个 int 元素分配内存空间,大小大约是 100 * sizeof(int)

重新设置容器大小

  • reserve() 用于请求容器在内部分配至少 n个元素的存储空间,以减少动态分配的次数。它不会改变容器的大小,只是调整内部容量(capacity)。
  • resize() 用于改变容器的大小到 n。如果新大小大于当前大小,容器会增加元素,新增的元素会被初始化为零或默认值;如果新大小小于当前大小,超出部分的元素会被删除

内存方面

  • reserve(): 只影响容量(capacity),不会导致元素的复制或移动,不会改变当前存储的元素。
  • resize(): 会改变大小(size),可能会导致元素的移动和复制,特别是在增加元素时。

lambda表达式

在这里插入图片描述
捕获列表:决定 lambda 可以访问哪些外部变量,以及以何种方式访问。
参数列表:与普通函数一致,定义 lambda 接受的输入参数。
返回类型:可选,如果不写,编译器会自动推导。
函数体:包含具体的逻辑实现。

  • capture(捕获列表): 用于指定lambda表达式可以访问的外部变量。捕获列表的常见方式包括:
    值捕获:[x]:将变量 x 的值复制到 lambda 内部。
    引用捕获:[&x]:将变量 x 的引用传入 lambda,允许在 lambda 内部修改原始变量。
    捕获所有(值):[=]:将所有外部变量按值捕获。
    捕获所有(引用):[&]:将所有外部变量按引用捕获。
    混合捕获:[=, &x]:将所有外部变量按值捕获,但 x 按引用捕获。
  • parameters(参数列表): 与普通函数的参数列表相同,定义lambda接受的输入参数,可以为空。
  • return_type(返回类型,可选): 用于指定返回值的类型。如果不写,编译器会根据函数体自动推导返回类型。
  • function body(函数体):包含实际的代码逻辑。

在C++中,lambda表达式(或称为匿名函数)是一种用于定义可调用对象(如函数对象)的语法糖。它的本质是提供一种方便的方式来创建和使用小的、临时的函数对象。lambda表达式可以被用作参数传递给函数,或者作为返回值。

当你在代码中使用 lambda 表达式时,编译器会将其转换为一个具体的类型,通常是一个匿名的、唯一的类。这使得 lambda 表达式不仅可以被调用,还可以携带状态(即捕获的变量)。

即使它们的结构相同,但由于捕获的变量不同,编译器会生成不同的类。
成员函数 operator():编译器会为这个类定义一个 operator() 方法,使得你可以像调用普通函数一样调用这个 lambda。

指针和引用的区别

指针(Pointer):指针是一个变量,它存储另一个变量的内存地址。通过指针可以间接访问或修改指针指向的变量。
引用(Reference):引用是某个已有变量的别名,引用在创建时必须初始化,并且不能再改变指向其他变量。一旦绑定到某个变量,引用就无法指向其他变量。

解释性语言和编译性语言区别

解释性语言:
Python,JavaScript,Ruby
编译性语言:
C,C++,Rust

解释性语言:
即时执行代码是逐行解释执行的,通常没有生成独立的可执行文件。解释器在运行时读取源代码,逐行解析并执行。
平台无关性:只要有合适的解释器,可以在任何平台上运行同样的源代码。

编译性语言:
先编译后执行代码首先通过编译器转换为机器语言(或中间代码),生成一个独立的可执行文件,之后运行时直接执行该可执行文件。
性能较高:编译后的代码是机器可直接执行的,通常比解释型语言更高效。

内存使用
解释性语言:由于代码是在执行时逐行解释,通常需要更多的内存来加载解释器和源代码。
编译性语言:编译后的程序是机器代码,执行时不需要加载解释器,所以内存使用通常更高效。
修改后的行为
解释性语言:修改代码后可以直接运行,修改和测试的周期较短。
编译性语言:修改后需要重新编译才能运行,因此调试周期较长。
调试与错误处理
解释性语言:错误通常在运行时发生,调试过程比较灵活,但可能遇到更难以追踪的错误(如运行时错误)。
编译性语言:错误通常在编译阶段被发现,错误信息相对较为清晰,有助于尽早发现问题。

Java
Java 既不是单纯的解释性语言,也不是单纯的编译性语言,它是两者的结合,采用了 编译+解释 的执行方式。具体来说,Java 采用了一种编译和解释相结合的机制,这种机制被称为 “编译-解释混合模式”。以下是更详细的说明:

Java 的执行流程
源代码编译:

当你编写 Java 程序时,首先会使用 Java 编译器(如 javac)将 .java 源代码编译成 字节码(即 .class 文件)。这个过程就是编译。
字节码是一种中间语言,它与平台无关,不是机器码,而是Java虚拟机(JVM)可以理解的指令。
字节码的执行:

生成的字节码不会直接运行在硬件上,而是由 Java 虚拟机(JVM) 来解释执行。
JVM 会将字节码 解释 成具体平台的机器码,然后在该平台上执行。这个过程类似于解释性语言的运行机制。
在现代 JVM 中,还引入了 即时编译(JIT,Just-In-Time compilation) 技术。JIT 会在运行时将热点字节码(即被频繁执行的部分)动态编译成机器码,以提高程序的执行效率。

C++内存泄漏可能的原因

内存泄漏是指程序在申请内存后,未能正确释放,导致系统可用内存逐渐减少,最终可能引发程序崩溃或系统性能下降。

  1. 程序员在动态分配内存后,忘记使用 delete 或 delete[](对于数组)来释放内存。

  2. 构造函数中使用裸指针(int*, char* 等)来分配内存,但没有适当的内存管理机制(如智能指针),那么如果在析构函数没有释放内存的话,会造成内存泄漏。

  3. 异常导致的提前返回
    当程序出现异常时,如果在栈展开过程中有动态分配的内存没有被释放,就会发生内存泄漏。特别是在没有使用 try-catch 块的情况下,异常会导致提前退出函数,而此时未释放的内存会被遗弃。

  4. 智能指针循环引用

  5. 内存管理不当的多线程问题
    在多线程程序中,如果一个线程分配了内存,而另一个线程错误地释放了它,或者某个线程没有适当地释放内存,就会出现内存泄漏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/913614.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

「QT」几何数据类 之 QVector2D 二维向量类

✨博客主页何曾参静谧的博客📌文章专栏「QT」QT5程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

运维智能化转型:AIOps引领IT运维新浪潮

1. AIOps是什么? AIOps(Artificial Intelligence for IT Operations),即人工智能在IT运维中的应用,通过机器学习技术处理运维数据(如日志、监控信息和应用数据),解决传统自动化运维…

C++练习 二维数组的应用

1&#xff09;超女有3个小组&#xff0c;每组有4名选手&#xff0c;请提供一个界面&#xff0c;输入每个超女的体重&#xff0c;然后&#xff0c;计算出每组的超女的平均体重和全部超女的平均体重。 #include <iostream> using namespace std;int main() {float sum1 0…

Vue3安装、创建到使用

vue安装 npm install vuenext # 全局安装 vue-cli npm install -g vue/cli #更新插件 项目中运行 vue upgrade --nextvue create 命令 vue create [options] <app-name> options 选项可以是&#xff1a; -p, --preset <presetName>&#xff1a; 忽略提示符并使用已…

JavaWeb:文件上传1

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

第2章2.3立项【硬件产品立项的核心内容】

硬件产品立项的核心内容 2.3 硬件产品立项的核心内容2.3.1 第一步&#xff1a;市场趋势判断2.3.2 第二步&#xff1a;竞争对手分析1.竞争对手识别2.根据竞争对手分析制定策略 2.3.3 第三步&#xff1a;客户分析2.3.4 第四步&#xff1a;产品定义2.3.5 第五步&#xff1a;开发执…

视频播放相关的杂记

基于QT FFMPEG设计一款 RTMP协议推流、视频录制软件 实现的功能&#xff1a; &#xff08;1&#xff09;将摄像头视频流 麦克风音频流合并&#xff0c;并推到流媒体服务器 &#xff08;2&#xff09;将摄像头视频流 麦克风音频流保存到本地磁盘 基于QtFFMPEG设计一款RTM…

oracle如何创建两个数据库,以及如何用navicat连接,监听、数据泵

项目背景oracle11g, 已经非常老了&#xff0c; 2017年的左右&#xff1b;谨慎参考 W11直接搜索就行 dbca唯一需要注意的地方就是一定一定一定要以管理身份运行&#xff0c;否则会提示各种因为文件权限问题报的错误 然后弹出程序提示&#xff0c;图形化开始操作了&#xff1b; …

LeetCode 509.斐波那契数

动态规划思想 五步骤&#xff1a; 1.确定dp[i]含义 2.递推公式 3.初始化 4.遍历顺序 5.打印dp数组 利用状态压缩&#xff0c;简化空间复杂度。在原代码中&#xff0c;dp 数组保存了所有状态&#xff0c;但实际上斐波那契数列的计算只需要前两个状态。因此&#xff0c;我们…

Qml 中的那些坑(七)---ComboBox嵌入Popup时,滚动内容超过其可见区域不会关闭ComboBox弹窗

【写在前面】 最近在写信息提交 ( 表单 ) 的窗口时发现一个奇怪的 BUG&#xff1a; 其代码如下&#xff1a; import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Window 2.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")B…

Softing工业将在纽伦堡SPS 2024上展示Ethernet-APL现场交换机

今年&#xff0c;Softing工业将在纽伦堡SPS贸易展览会上展示aplSwitch Field —— 一款先进的过程自动化解决方案。这款16端口以太网高级物理层&#xff08;APL&#xff09;现场交换机的防护等级高达IP30&#xff0c;可提供从应用到现场级别的无缝以太网连接&#xff0c;专为Ex…

Local Transfer 致力于更加便捷地共享传输文件

软件主页&#xff1a;https://illusionna.github.io/LocalTransfer

分布式——BASE理论

简单来说&#xff1a; BASE&#xff08;Basically Available、Soft state、Eventual consistency&#xff09;是基于CAP理论逐步演化而来的&#xff0c;核心思想是即便不能达到强一致性&#xff08;Strong consistency&#xff09;&#xff0c;也可以根据应用特点采用适当的方…

22.04Ubuntu---ROS2使用rclcpp编写节点C++

节点需要存在于功能包当中&#xff0c;功能包需要存在于工作空间当中。 所以我们要想创建节点&#xff0c;就要先创建一个工作空间&#xff0c;再创建功能包。 第一步&#xff1a;创建工作空间 mkdir -p chapt2_ws/src/ 第二步&#xff1a;创建example_cpp功能包&#xff0c…

《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接

《TCP/IP网络编程》学习笔记 | Chapter 7&#xff1a;优雅地断开套接字连接 《TCP/IP网络编程》学习笔记 | Chapter 7&#xff1a;优雅地断开套接字连接基于 TCP 的半关闭单方面断开连接带来的问题套接字和流针对优雅断开的 shutdown 函数为何需要半关闭&#xff1f;基于半关闭…

使用 .NET Core 7 和 SignalR 构建实时聊天应用程序

动动你可爱的小手&#xff0c;请关注下本人公众号&#xff0c;继续为您提供更多原创技术文章。谢谢给为的支持 SignalR 是一个 ASP.NET 库&#xff0c;它支持实时 Web 功能&#xff0c;允许服务器立即将更新推送到客户端&#xff0c;从而提高应用程序的效率和响应能力。它通过简…

智慧社区可视化解决方案:科技引领社区服务与管理新篇章

随着社会的发展&#xff0c;智慧社区作为新型城镇化发展目标和社区服务体系建设的重要举措&#xff0c;正逐步改变着我们的生活方式。智慧社区通过综合运用现代科学技术&#xff0c;整合区域资源&#xff0c;提升社区治理和服务水平&#xff0c;为居民提供更为便捷、高效、安全…

Unicode字符集(万国码)

1.三种编码方式&#xff1a; UTF-16&#xff1a;16个bit位&#xff08;2个字节&#xff09;存储 UTF-32&#xff1a;32个bit位&#xff08;4个字节&#xff09;存储 UTF-8&#xff1a;可变长度字符编码。1-4个字节存储&#xff0c;只需记住&#xff1a;英文字母1个字节表示&…

excel功能

统计excel中每个名字出现的次数 在Excel中统计每个名字出现的次数&#xff0c;您可以使用COUNTIF函数或数据透视表。以下是两种方法的详细步骤&#xff1a; 方法一&#xff1a;使用COUNTIF函数 准备数据&#xff1a;确保您的姓名列表位于一个连续的单元格区域&#xff0c;例如…

A025-基于SpringBoot的售楼管理系统的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…