小谈类机制相关

2023-10-27

小谈类机制相关

本文主要涉及类相关的一些常见面试问题,以及相关特性。
包括 this 指针、拷贝构造函数相关以及类机制。

一、this指针

编译器在编译普通成员函数时,会隐式的分配一个形参指针,即this指针。并且当实例化对象调用该成员函数时,会把当前对象的地址赋值给this指针

1、this指针是常量指针

**this指针是常量指针,指向不可改变。**当使用const 关键字修饰成员函数时,该指针即是常量指针,又是指针常量,指向和指向的值都不可改变。

2、this 指针只存在于普通成员函数中

this指针是编译器为普通成员函数分配的隐式形参,对于静态成员函数和友元函数来说,都是没有 this指针的,因此一般双目运算符的重载都使用全局函数做友元的形式。
另外我们知道,返回局部变量的地址和引用会造成不可估计后果。但是在拷贝构造函数等成员函数中都会返回this指针的解引用,因为其是传入的有效形参,是有明确地址的。

3、成员函数中delete this 会发生什么?

1)禁止在析构函数中使用 delete this。因为delete this 会不断的调用本对象的析构函数,而析构函数中又会调用delete this,形成无线递归,从而造成堆栈溢出。
2)在普通成员函数中调用 delete this, 需要区分是栈对象和堆对象。因为delete this会执行析构函数,并释放内存。那么对于堆对象来说会执行析构,并且释放内存,那么当再次访问时就会出现内存问题;对于栈对象来说会执行析构,但是不会释放内存,那么再次访问也会出现内存错误。

二、拷贝构造函数

定义一个类实际就是声明一个组合类型,而构造函数就是初始化(成员变量赋值)的过程。拷贝构造函数就是根据一个现有的对象作为基础去创建一个新的对象。

1、为什么拷贝构造函数中形参一般使用const + &?

1)使用 & 是为了避免递归调用拷贝构造函数,从而造成堆栈溢出
2)使用const 是因为形成 常量左值引用,可以支持传入左值、右值、常量左值和常量右值,相当于扩大了可传入参数的类型范围

2、深浅拷贝与移动语义

1)浅拷贝。
两个指针指向同一块内存,容易造成 内存的重复释放问题。
2)深拷贝。
重新申请一块内存,然后再进行赋值操作。不会造成内存的重复释放,但是存在内存开销问题。
3)移动构造函数
主要是应用于临时变量的拷贝,减少不必要的内存开销问题。

3、拷贝构造函数和赋值操作符区别

1)拷贝构造函数是构造函数,而赋值操作符重载是成员函数
2)另外就是拷贝构造函数是去完成对未初始化的存储区的初始化,而赋值操作符是处理一个已经存在的对象。

三、类机制

1、class 和 struct 的区别

在C中struct中是不能存放函数的,如果想要实现封装、继承等特性需要使用函数指针。
在C++中class 和 struct 都是可以实现继承和多态的。区别是默认的访问权限不一样。

2、类在什么情况下不能被继承?

1)使用 final 关键字
2)构造函数私有化
3)虚继承 + 友元

3、当发生多种继承时类的构造顺序(虚继承、抽象类继承、普通继承)

静态成员> 虚基类> 抽象类> 基类 > 成员变量(按照声明顺序)> 派生类

4、类的大小

1)字节对齐
2)虚函数(虚函数表指针占用 8个字节)
3)虚继承(虚基类表指针占用8个字节)
4)空类的大小为1个字节。主要是用于区分不同的对象。

5、如何限制只能在栈上创建对象?

C++只有使用new 关键字,对象才会建立在堆上。并且C++允许重载operator new 运算符,那么只要讲operator new 运算符进行重载并私有化即可。

6、如何限制只能在堆上创建对象?

类对象只能建立在堆上,就是不能静态建立类对象,即不能直接调用类的构造函数。 容易想到将构造函数设为私有。在构造函数私有之后,无法在类外部调用构造函数来构造类对象,只能使用new运算符来建立对象。然而,前面已经说过,new运算符的执行过程分为两步,调用new 时仍然需要调用构造函数。
当对象建立在栈上面时,是由编译器分配内存空间的,调用构造函数来构造栈对象。当对象使用完后,编译器会调用析构函数来释放栈对象所占的空间。编译器管理了对象的整个生命周期。如果编译器无法调用类的析构函数,情况会是怎样的呢?比如,类的析构函数是私有的,编译器无法调用析构函数来释放内存。所以,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性,其实不光是析构函数,只要是非静态的函数,编译器都会进行检查。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。

7、如何判断类/结构体对象是否相等? 能否使用memcmp函数进行逐字符判断

1)判断类/结构体对象是否相等需要重载比较运算符(==)。
2)不可以使用memcmp函数进行比较。因为memcmp是进行逐字节比较的,而结构体在保存时进行了字节对齐,而在字节对齐的过程中的填充是随机的,因此无法直接进行比较。

四、成员初始化列表

采用初始化列表,成员初始化的顺序就是根据变量声明的顺序。

1、为什么使用成员初始化列表要比在构造函数中初始化要快一点?

严格来说,在构造函数中执行的是赋值操作,并不是初始化操作;因为在对象的构造顺序中,成员的初始化要比构造函数的初始化早;
那么如果使用构造函数对自定义成员对象进行赋值会执行两步(默认构造函数 + 拷贝赋值), 而如果使用成员初始化列表,则不会执行默认构造函数,而是直接根据初始化列表中传入的参数进行相应的成员构造。减少了不必要的开销。

2、三种情况必须使用成员初始化列表

1)引用类型成员(初始化时必须要进行赋值)
2)常量类型成员(初始化后不能被赋值,只能在初始化时赋值)
3)没有默认构造函数的成员类型(比如只重载了默认构造函数,那么该成员就没有默认的无参构造函数可以调用,就会出错)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小谈类机制相关 的相关文章

随机推荐

  • IDEA如何导入Eclipse项目-靠谱

    小伙伴在用到IDEA的时候 将已有的Eclipse项目导入到IDEA中 遇到各种问题 我总结了一下 仅供参考 我的工具版本是 IntelliJ IDEA 2017 1 5 1 open的项目目录展示 实际文件目录 打开的项目目录展示 2 点
  • Java High Level REST Client 中文API(仅供参考)

    1 初始化 兼容性 Java High Level REST Client需要Java 1 8 并依赖于Elasticsearch核心项目 客户端版本与客户端开发的Elasticsearch版本相同 它接受与TransportClient相
  • PyQt的动作(QAction)

    前言 Qt的设计师程序能够识别用户界面中用户做同样事情时所经常使用的不同种方法 例如 在许多应用中创建一个新文件可以使用File gt New菜单项 或者通过点击按钮图标 或者使用快捷键等 对于用户是如何执行动作的我们并不关心 关心他们到底
  • 第一章: Mysql体系结构和存储引擎

    文章目录 1 1 定义数据库和实例 1 2 Mysql体系结构 1 3 Mysql存储引擎 1 4 常见问题解答 1 5 存储引擎相关操作语法 1 6 连接Mysql 1 1 定义数据库和实例 数据库和实例的区别 数据库是物理操作系统或其他
  • 让别人写一个python爬虫程序大概要多少钱?

    前言 目前 对于程序代做来说没有统一标准 不像论文那样可以按照字数来定价 根据行业经验 总结出了一个python代写的参考价格 一般来说如果想写本科的python作业 一般是500起 硕士作业按照项目算的话 一般是1500起 影响pytho
  • JS的作用域问题

    一 块级作用域 在 JavaScript 中 作用域为可访问变量 对象 函数的集合 js没有块级作用域 你可以自己闭包或其他方法实现 只有函数级作用域 函数外面的变量函数里面可以找到 函数里面的变量外面找不到 var a 10 functi
  • Nginx 七层和四层负载均衡——筑梦之路

    七层负载均衡示例配置 worker processes 2 events worker connections 1024 7层http负载 http include mime types default type application o
  • Python全栈开发【基础-07】与用户交互

    专栏介绍 本专栏为Python全栈开发系列文章 技术包括Python基础 函数 文件 面向对象 网络编程 并发编程 MySQL数据库 HTML JavaScript CSS JQuery bootstrap WSGI Django Flas
  • C++ list, vector, map, set 区别与用法比较

    一 list和vector List封装了链表 Vector封装了数组 list和vector得最主要的区别在于vector使用连续内存存储的 他支持 运算符 而list是以链表形式实现的 不支持 Vector对于随机访问的速度很快 但是对
  • 华为OD机试真题 Java 实现【组合出合法最小数】【2023Q1 200分】,附详细解题思路

    一 题目描述 给一个数组 数组里面都是代表非负整数的字符串 将数组里所有的数值排列组合拼接起来组成一个数字 输出拼接成的最小的数字 二 输入描述 一个数组 数组不为空 数组里面都是代表非负整数的字符串 可以是0开头 例如 13 045 09
  • Tkinter模拟发送邮箱验证码并在指定时间后验证码过期

    先上两张图 再解释 运行原理 程序运行后 输入要接收验证码的邮箱地址 点击 发送 后 控制台打印输出得到的验证码并发送到邮箱里 过了15秒以后 验证码再次刷新 并打印输出 这样就实现了动态过期 原理就是到某个时间点我再刷新一遍生成验证码函数
  • Hadoop命令大全

    目录 基本语法 一 上传 二 下载 三 其他增删改查操作 3 1 增 3 2 删 3 3 改 3 4 查 基本语法 hadoop fs 和 hdfs dfs hadoop fs和hdfs dfs命令等效 hdfs dfs 只能操作HDFS文
  • FISCO-BCOS学习——区块链浏览器搭建

    注意 本系列文章遇到的问题都可以参考查找 官方文档 或 本系列问题总结 FISCO BCOS 及 WeBase 问题记录 FISCO BCOS 官方文档 WeBase 官方文档 FISCO BCOS区块链浏览器搭建 前提条件 环境 版本 J
  • STM32的HAL库SPI操作(master 模式)-根据时序图配置SPI

    SPI相关基础知识 SPI基本概念请自行百度 参考 百度百科SPI简介 我们讲重点和要注意的地方 master模式下要关注的地方 接线一一对应 也就是说主控的MISO MOSI SCLK CSn 分别和设备的MISO MOSI SCLK C
  • 数据清洗之朝阳医院2018年销售数据分析

    朝阳医院2018年销售数据分析 所用到的数据提取地址 gt 戳这里下载 或私我 过程 整体代码 导入库 import pandas as pd import numpy as np import matplotlib pyplot as p
  • STM32F103ZET6---【硬件篇】定时器

    STM32的TIM1 TIM8为高级定时器 TIM2 TIM3 TIM4 TIM5为通用定时器 TIM6 TIM7为基本定时器 各个定时器引脚如下 TIM1和TIM8定时器的功能包括 16位向上 向下 向上 下自动装载计数器 16位可编程
  • RealBasicVSR训练(三)用自己的数据集训练

    由于上一篇中的方法只能用1个gpu训练 故重新采取之前的训练方法 第一步 RealBasicVSR master mim train mmedit configs realbasicvsr wogan c64b20 2x30x8 lr1e
  • 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java基于HTML5的流浪动物领养平台yww0b

    很多大学生 成考 自考 全日制本科 大专的学生都因为毕设没有完成而延时毕业的情况 现在分享给大家选题 下面有2023年做的选题 最后面有选题 源码 论文下载网站给大家学习 如今计算机技术的飞速发展 大约三 四年前 软件工程是市场的热门领域
  • 电荷泵电路(Charge Pump)用于升压的解析

    升压的电荷泵电路 Charge Pump 也称为开关电容转换器 Switched Capacitor Converter 老粉丝都知道 公众号很久之前就发布了一篇阐述电感 电容 二极管构成的BOOST升压方案的文章 那为什么还要讨论电荷泵方
  • 小谈类机制相关

    小谈类机制相关 本文主要涉及类相关的一些常见面试问题 以及相关特性 包括 this 指针 拷贝构造函数相关以及类机制 一 this指针 编译器在编译普通成员函数时 会隐式的分配一个形参指针 即this指针 并且当实例化对象调用该成员函数时