【C++ 面试 - 基础题】每日 3 题(七)

news2024/9/23 1:26:39

✍个人博客:Pandaconda-CSDN博客

📣专栏地址:http://t.csdnimg.cn/fYaBd

📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

 19. C++ 中 const 和 static 的作用

static

  • 不考虑类的情况

    • 隐藏。所有不加 static 的全局变量和函数具有全局可见性,可以在其他文件中使用,加了之后只能在该文件所在的编译模块中使用。

  

  • 默认初始化为 0,包括未初始化的全局静态变量与局部静态变量,都存在全局未初始化区。

  • 静态变量在函数内定义,始终存在,且只进行一次初始化,具有记忆性,其作用范围与局部变量相同,函数退出后仍然存在,但不能使用。

  • 考虑类的情况

    • static 成员变量:只与类关联,不与类的对象关联。定义时要分配空间,不能在类声明中初始化,必须在类定义体外部初始化,初始化时不需要标示为 static;可以被非 static 成员函数任意访问。

    • static 成员函数:不具有 this 指针,无法访问类对象的非 static 成员变量和非 static 成员函数;不能被声明为 const、虚函数和 volatile;可以被非 static 成员函数任意访问。

从面向过程角度回答

  • static 修饰全局变量

    • 在符号表中,符号的作用域就从 globle 变成了 local(static 修饰函数也会这样)。

  • static 修饰局部变量

    • 局部变量本身不产生符号,通过 ebp - 偏移量 来访问。

注意:全局变量、静态全局变量、静态局部变量都在静态存储区分配空间,而局部变量在栈分配空间。

两个编译单元相同名字的 static 函数会报错吗?

不会,因为 static 具有隐藏特性。

存储区域

  • 由 static 修饰的变量存储在虚拟内存空间的数据区,而非静态成员变量一般存放在堆区或者栈区(全局变量和常量也存放在数据区)。

  • 由 static 修饰的函数以及非静态函数都存在于存储在虚拟地址空间的代码区。

const

  • 不考虑类的情况

    • const 常量在定义时必须初始化,之后无法更改。

    • const 形参可以接收 const 和非 const 类型的实参,例如:

      // i 可以是 int 型或者 const int 型
      void fun(const int& i){ 
          //...
      }
  • 考虑类的情况

    • const 成员变量:不能在类定义外部初始化,只能通过构造函数初始化列表进行初始化,并且必须有构造函数;不同类对其 const 数据成员的值可以不同,所以不能在类中声明时初始化。

    • const 成员函数:const 对象不可以调用非 const 成员函数;非 const 对象都可以调用;不可以改变非 mutable(用该关键字声明的变量可以在 const 成员函数中被修改)数据的值。

      void Print() const{
          //实现
      }

补充一点 const 相关:const 修饰变量也是与 static 有一样的隐藏作用。只能在该文件中使用,其他文件不可以引用声明使用。因此在头文件中声明 const 变量是没问题的,因为即使被多个文件包含,链接性都是内部的,不会出现符号冲突。

const 替换特性

编译过程中,把出现常量名字的地方,用常量的值进行替换。

const int a = 10;
int* p = (int)*a;
*p = 20;
cout<< a << " " << *p << endl;

上面输出结果是 10 20,这是因为 a 在编译过程中会被替换成 10。

const 和 static 的区别

面向过程:

  • const:全局变量、局部变量、形参变量,且不能修饰函数。

  • static:全局变量、局部变量,且可以修饰函数。

面向对象:

  • const:常方法、成员变量,函数调用依赖对象即有 this 指针。

  • static:静态方法、成员变量,函数调用不依赖对象即没有 this 指针。

 

20. final 和  override 关键字 

override

当在父类中使用了虚函数时候,你可能需要在某个子类中对这个虚函数进行重写,以下方法都可以: 

class A
{
    virtual void foo();
}
class B : public A
{
    void foo(); //OK
    virtual void foo(); // OK
    void foo() override; //OK
}

如果不使用 override,当你手一抖,将 foo() 写成了 f00() 会怎么样呢?结果是编译器并不会报错,因为它并不知道你的目的是重写虚函数,而是把它当成了新的函数。如果这个虚函数很重要的话,那就会对整个程序不利。所以,override 的作用就出来了,它指定了子类的这个虚函数是重写的父类的,如果你名字不小心打错了的话,编译器是不会编译通过的:

class A
{
    virtual void foo();
};
class B : public A
{
    virtual void f00(); //OK,这个函数是B新增的,不是继承的
    virtual void f0o() override; //Error, 加了override之后,这个函数一定是继承自A的,A找不到就报错
};

final

当不希望某个类被继承,或不希望某个虚函数被重写,可以在类名和虚函数后添加 final 关键字,添加 final 关键字后被继承或重写,编译器会报错。例子如下:

class Base
{
    virtual void foo();
};
 
class A : public Base
{
    void foo() final; // foo 被override并且是最后一个override,在其子类中不可以重写
};

class B final : A // 指明B是不可以被继承的
{
    void foo() override; // Error: 在A中已经被final了
};
 
class C : B // Error: B is final
{
};

21. vo latile、mutable 和 explicit 关键字的用法

(1)volatile

主要用于告诉编译器不要对其所修饰的变量进行优化,因为这些变量可能会在程序执行过程中被外部因素改变,而编译器不应该假定它们的值是稳定的。

  1. volatile 的作用:

    1. volatile 主要用于修饰变量,告诉编译器不要对该变量进行优化。这通常用于描述一些可能会被外部因素(如硬件、操作系统、其他线程等)更改的变量。

  2. 使用场景:

    1. 硬件寄存器:volatile 可用于描述与硬件寄存器通信的变量,因为这些变量的值可能在编译器无法预测的时间被硬件更改。

    2. 多线程编程:在多线程环境中,一个线程修改的变量可能会被另一个线程读取,这时 volatile 可以确保对变量的读取和写入不会被优化掉,比如不要从各自的寄存器中读取该变量。

    3. 信号处理器中使用:在信号处理器中,被信号处理函数修改的变量应该声明为 volatile,以确保编译器不会对它们进行优化。

  3. 不足之处:

    1. volatile 仅告诉编译器不要对变量进行优化,但它并不能解决多线程并发问题。在多线程环境中,还需要使用更强大的同步机制(如互斥锁、条件变量等)来确保线程安全性。

    2. volatile 并不适用于所有情况,因为它仅告诉编译器不要优化,但不提供同步机制。如果需要精确的同步和互斥,应该使用其他多线程编程工具。

示例

volatile int hardwareRegister; // 描述硬件寄存器的变量

void signalHandler(int sig) {
    volatile bool flag = true; // 信号处理器中的变量
    // ...
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 总之,volatile 关键字用于告诉编译器不要对变量进行优化,通常用于描述那些可能被外部因素改变的变量。在多线程环境中,它应该与其他同步机制一起使用来确保线程安全性。但需要注意,volatile 并不是解决多线程问题的最终解决方案,更复杂的同步机制可能需要用于确保数据一致性。

(2)mutable

mutable 的中文意思是 “可变的,易变的”,跟 constant(既 C++ 中的 const)是反义词。在 C++ 中,mutable 也是为了突破 const 的限制而设置的。被 mutable 修饰的变量,将永远处于可变的状态,即使在一个 const 函数中。我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成 const 的。但是,有些时候,我们需要在 const 函数里面修改一些跟类状态无关的数据成员,那么这个函数就应该被 mutable 来修饰,并且放在函数后后面关键字位置

注意:mutable 只能作用于类的非静态和非常量数据成员。 

样例

class person
{
    int m_A;
    mutable int m_B;//特殊变量 在常函数里值也可以被修改
public:
     void add() const//在函数里不可修改this指针指向的值 常量指针
     {
        m_A=10;//错误  不可修改值,this已经被修饰为常量指针
        m_B=20;//正确
     }
}

class person
{
    int m_A;
    mutable int m_B;//特殊变量 在常函数里值也可以被修改
}
int main()
{
    const person p;//修饰常对象 不可修改类成员的值
    p.m_A=10;//错误,被修饰了指针常量
    p.m_B=200;//正确,特殊变量,修饰了mutable
}

(3)explicit

explicit 关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换,注意以下几点:

  • explicit 关键字只能用于类内部的构造函数声明上。

  • explicit 关键字作用于单个参数的构造函数。

  • 被 explicit 修饰的构造函数的类,不能发生相应的隐式类型转换。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ImportError: DLL load failed while importing _rust: 找不到指定的程序的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

网络协议四 物理层,数据链路层

从这一节开始学习 五层模型。学习方法是从最底层物理层开始学习 七层模型 五层模型 各个层用的协议&#xff0c;以及加上协议后的称谓 各个层的作用 应用层&#xff1a;可以认为是原始数据&#xff0c;该数据称为 报文&#xff0c;用户数据。 运输层&#xff1a;也叫传输层&am…

【Linux】1w字详解自定义Shell管道 | 构建简易进程池

目录 续&#xff1a;通信 4 种情况 应用场景 1. 自定义 shell 管道 1. 包含头文件 2. 解析命令函数 详细步骤 3. 执行命令函数 4. 主函数 总结 2. 使用管道实现一个简易版本的进程池 代码结构 代码实现 channel.hpp tasks.hpp main.cc 子进程读取任务&#xff…

Stable Diffusion绘画 | 提示词基础原理

提示词之间使用英文逗号“,”分割 例如&#xff1a;1girl,black long hair, sitting in office 提示词之间允许换行 但换行时&#xff0c;记得在结尾添加英文逗号“,”来进行区分 权重默认为1&#xff0c;越靠前权重越高 每个提示词自身的权重默认值为1&#xff0c;但越靠…

Al+CRM:企业增长新引擎

在企业中&#xff0c;GenAI可以帮助改进决策制定、优化运营流程、增强产品和服务的创新能力&#xff0c;以及提供更加个性化的客户体验&#xff0c;在Gartner的调研中&#xff0c;AI将在以下领域发挥重要作用。 AICRM,将改变原有CRM的使用体验。把抽屉式的系统操作&#xff0c;…

【ubuntu20.04 运行sudo apt-get upgrade报错】

ubuntu20.04 运行sudo apt-get upgrade报错 1 确保系统是最新的2 检查你的软件源列表是否正确无误3 修改软件源3.1 备份原来的源3.2 更换源3.2.1 Ubuntu20.04(focal)阿里云软件源3.2.2 Ubuntu20.04清华软件源 3.3 更新软件源 4 修复升级5 重新安装特定软件包6 导入缺失的密钥 1…

7.1.算法分析与设计-算法分析基本概念与算法分析基础

很难 算法基础知识 算法是对特定问题求解步骤的一种描述&#xff0c;它是指令的有限序列&#xff0c;其中每一条指令表示一个或多个操作。简单的说算法就是某个问题的解题思路&#xff0c;算法的五个重要特性如下&#xff1a; 有穷性。一个算法必须总是&#xff08;对任何合…

数据结构——优先队列

文章目录 一、基本介绍二、基本操作三、实现1 实现的思路2 大顶堆实现2.1 概念2.2 完全二叉树的实现方式2.3 优先队列的图示2.4 对于基本操作实现的讲解2.4.1 检查队列是否为空 ( isEmpty )2.4.2 检查队列是否已满 ( isFull )2.4.3 查看 ( peek )2.4.4 插入 ( offer )2.4.5 删除…

计算数学精解【5】-prolog计算精解(1)

文章目录 概述什么是prolog安装 基础控制台增加规则参考文献 概述 什么是prolog Prolog&#xff08;Programming in Logic&#xff09;是一种面向演绎推理的逻辑型程序设计语言&#xff0c;最早于1972年由柯尔麦伦纳&#xff08;Colmeraner&#xff09;及其研究小组在法国马赛…

Python教程(十三):常用内置模块详解

目录 专栏列表1. os 模块2. sys 模块3. re 模块4. json 模块5. datetime 模块6. math 模块7. random 模块8. collections 模块9. itertools 模块10. threading 模块 总结 专栏列表 Python教程&#xff08;十&#xff09;&#xff1a;面向对象编程&#xff08;OOP&#xff09;P…

uniapp h5本地预览pdf教程 (含白屏|跨域解决方案)

第一步 下载pdf.js 很多pdf.js版本在真机ios环境都会白屏 经测试后2.5.207版本比较稳定&#xff0c;Android和IOS环境PDF文件都能加载成功 下载地址 https://github.com/mozilla/pdf.js/releases/tag/v2.5.207https://github.com/mozilla/pdf.js/releases/tag/v2.5.207第二步 解…

leetcode50. Pow(x, n),快速幂算法

leetcode50. Pow(x, n)&#xff0c;快速幂算法 实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xn &#xff09;。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000 示例 2&#xff1a; 输入&#xff…

贵阳高新区:加强数字人才培育 引领数字经济未来

在近期举行的贵阳高新区&#xff08;贵州科学城&#xff09;2024年科技创新与成果交流夏季活动中&#xff0c;来自清华大学2022级大数据&#xff08;贵州&#xff09;全日制工程硕士专业的学生们展示了他们在城市公交数据挖掘、通勤线路优化、场景数据的稳定训练以及营运车辆风…

数据分析:多诊断指标ROC分析

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 介绍 pROC::roc函数能够使用一个指标(predictor)去区分两个或多个分组(response),并计算95%置信区间的原理基于以下几个关键点: ROC曲线:ROC曲线是一种图形表示,用于展示分类模型在所有…

【轨物洞见】从电磁感应现象的发现和应用理解科学、技术、工程的关系

电磁感应现象是19世纪以来人类最伟大的发现。有了这个发现&#xff0c;才有后来电和无线电这两大改变人类命运的技术&#xff0c;第二次、第三次工业革命才会发生&#xff0c;人类财富才会猛增、我们的生活才会越来越美好。 让我们来回顾一下电磁感应现象的发现和应用&#xff…

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-05-数据架构规划与设计

文章目录 1 数据库设计与类的设计融合2. 数据库设计与XML设计融合 教材本节实在太敷衍了&#xff0c;没什么有用的内容 1 数据库设计与类的设计融合 不存在唯一正确的数据模型&#xff0c;然而却存在好的数据模型好模型的目标 将工程项目整个生存期内的花费减至最小 而不是单纯…

KL 散度(python+nlp)

python demo KL 散度&#xff08;Kullback-Leibler divergence&#xff09;&#xff0c;也称为相对熵&#xff0c;是衡量两个概率分布之间差异的一种方式。KL 散度是非对称的&#xff0c;也就是说&#xff0c;P 相对于 Q 的 KL 散度通常不等于 Q 相对于 P 的 KL 散度。 一个简…

zabbix7.0TLS-05-快速入门-触发器

文章目录 1 概述2 查看触发器3 添加触发器4 验证触发器5 查看问题6 问题恢复 1 概述 监控项用于收集数据&#xff0c;但是我们并不能时刻观测每个监控项的数据&#xff0c;看看哪个监控项的数据超过了正常可接受的数值或状态&#xff0c;比如 CPU 负载高于 90%、磁盘使用率低于…

不平衡数据:Handling Imbalanced Dataset with SMOTE导致ValueError ⚖️

不平衡数据&#xff1a;Handling Imbalanced Dataset with SMOTE导致ValueError ⚖️&#x1f4c8; 不平衡数据&#xff1a;Handling Imbalanced Dataset with SMOTE导致ValueError ⚖️&#x1f4c8;摘要引言详细介绍什么是不平衡数据集&#xff1f;⚖️SMOTE简介&#x1f4c8…

加密案例分享:电子设备制造行业

企业核心诉求选择 1.某企业规模庞大&#xff0c;分支众多&#xff0c;数据安全管理方面极为复杂&#xff1b; 2.企业结构复杂&#xff0c;包括研发、销售、财务、总部、分部、办事处、销售等单位连结成为一个庞大的企业组织&#xff0c;数据产生、存储、流转、使用、销毁变化…