C++经典面试题目(二)

1. C++中,static关键字有什么作用?

在C++中,static关键字有多种作用,包括限定作用域、保持变量内容持久化和修饰类成员等。以下是static关键字在C++中的主要作用:

  1. 限定作用域:当变量、函数或类成员被声明为static时,它们的作用域会被限制在声明它们的文件、函数或类内部。对于局部变量,static关键字会使其生命周期延长至整个程序运行期间,但作用域仍然局限于定义它的函数内部。对于全局变量或函数,static关键字则将其作用域限制在定义它们的文件内部,实现了隐藏的作用。
  2. 保持变量内容持久化:static变量在程序执行期间只会被初始化一次,且其值在函数调用之间保持不变。这使得static变量可以用于保存程序执行过程中的状态信息。
  3. 修饰类成员:在类中,static关键字可以用于修饰成员变量和成员函数。静态成员变量属于类而不是类的对象,因此所有对象共享同一个静态成员变量。静态成员函数也只能访问静态成员变量或其他静态成员函数,不能访问类的非静态成员。此外,静态成员函数可以在没有创建对象的情况下通过类名直接调用。
  4. 优化程序性能:static关键字还可以用于形成静态代码块以优化程序性能。静态代码块在类初次被加载时执行一次,常用于初始化静态成员变量或执行只需进行一次的操作。

需要注意的是,虽然static关键字具有多种作用,但应根据具体需求和场景来选择使用。过度或不当地使用static关键字可能会导致代码结构混乱、难以维护或引发潜在问题。

2. C++中,#define和const有什么区别?

在C++中,#defineconst都可以用来定义常量,但它们之间存在一些关键的区别。

  1. 定义与含义:

    • #define是C++预处理器的指令,用于定义宏。它实际上并不属于C++语言本身的一部分,而是在编译前的预处理阶段进行处理的。#define不仅可以定义常量,还可以定义函数、对象、类型等宏。
    • const是C++关键字,用于定义常量。它定义的是一个具有常量性质的变量,其值在程序运行期间不能被修改。const定义的常量具有类型,并且编译器会进行类型安全检查。
  2. 作用对象与类型检查:

    • #define定义的宏没有类型,仅仅是简单的文本替换。预处理器在编译前将程序中所有的宏替换为相应的文本,而不会进行类型检查。因此,使用#define定义的常量在编译时不会分配内存空间,也不会有存储与读内存的操作。
    • const定义的常量具有具体的类型,并且编译器会在编译阶段进行类型检查。这意味着如果你试图修改一个const常量的值,编译器会报错。此外,const常量会在内存中分配空间(可以是堆中也可以是栈中),尽管对于编译期间的常量,编译器通常会将它们保存在符号表中以提高效率。
  3. 编译器处理方式:

    • #define宏是在预处理阶段展开的,因此不能在调试阶段对宏定义进行调试。此外,由于宏只是简单的文本替换,所以在使用时需要特别小心宏展开后可能产生的副作用(如运算符优先级问题、多次展开等)。
    • const常量是在编译阶段进行处理的,因此可以在调试阶段对其进行调试。由于const常量具有类型并且编译器会进行类型检查,所以使用起来相对更安全。
  4. 存储方式与效率:

    • 如前所述,#define宏仅仅是文本替换,不会分配内存空间。这使得它在某些情况下可以节省空间,但也可能导致代码膨胀(因为宏展开可能会产生大量的重复代码)。
    • const常量会在内存中分配空间,但编译器通常会进行优化以减少不必要的内存分配。例如,对于编译期间的常量(即编译时已知其值的常量),编译器可能会将它们保存在符号表中而不是实际分配内存空间。这使得const常量在效率上也具有较高的表现。

综上所述,#defineconst在定义常量时具有不同的特点和使用场景。在实际编程中,应根据具体需求选择合适的常量定义方式。一般来说,推荐使用const来定义常量,因为它具有类型安全检查、编译器优化和更好的调试支持等优点。但在某些特定场景下(如需要定义复杂的宏或需要在多个文件中共享宏定义时),使用#define可能更为合适。

3. 静态链接和动态链接有什么区别?

静态链接和动态链接是两种不同的程序链接方式,它们在程序加载和执行时有着不同的行为和特性。以下是它们之间的主要区别:

  1. 链接时间:静态链接在程序编译时就将需要的库与程序的目标文件链接在一起,形成一个完整的可执行文件。而动态链接则是在程序运行时才将库加载到内存中,并与程序进行链接。

  2. 文件大小:由于静态链接将库文件直接嵌入到可执行文件中,因此生成的可执行文件通常较大。而动态链接仅需要在运行时加载库文件,因此可执行文件较小。

  3. 内存使用:静态链接的每个程序都会包含一份完整的库代码,如果多个程序同时运行,会浪费内存空间。而动态链接的库代码在内存中只有一份,多个程序可以共享使用,节省了内存空间。

  4. 更新和部署:如果静态链接的库需要更新,那么需要重新编译和链接整个程序。而动态链接的库可以独立更新,只需要替换原有的库文件,无需重新编译和链接程序。这使得动态链接在软件的更新和部署上更加灵活和方便。

  5. 依赖性:静态链接的程序不依赖于外部库文件,可以独立运行。而动态链接的程序需要依赖于相应的动态链接库文件,如果库文件缺失或版本不兼容,程序可能无法正常运行。

  6. 加载速度:静态链接的程序在启动时不需要加载额外的库文件,因此加载速度可能较快。而动态链接的程序在启动时需要加载和链接库文件,可能会稍微慢一些。然而,在实际应用中,这种差异通常并不明显。

总的来说,静态链接和动态链接各有优缺点,适用于不同的场景和需求。在选择链接方式时,需要考虑程序的大小、内存使用、更新和部署的灵活性以及依赖性等因素。

4. 变量的声明和定义有什么区别?

在C++中,变量的声明和定义具有特定的区别,尽管在实际代码中这两个概念经常是同时出现的。以下是它们之间的主要区别:

  1. 声明(Declaration)

    • 变量的声明是告诉编译器变量的名称和类型,但不为变量分配内存空间。
    • 它只是提供了一个变量的“蓝图”或“规范”,告诉编译器在程序的某个地方有一个具有特定类型的变量。
    • 声明可以在程序的多个位置进行,例如在头文件中或在函数原型中。
    • 例如:extern int x; 这是一个声明,它告诉编译器存在一个名为 x 的整型变量,但实际的内存分配发生在别处。
  2. 定义(Definition)

    • 变量的定义是为变量分配内存空间,并可能为其指定一个初始值。
    • 定义是变量实际“诞生”的地方,在这里编译器为变量分配内存,并可以在需要时存储数据。
    • 对于给定的变量,定义只能在一个地方进行(否则会导致重复定义的错误)。
    • 例如:int x = 10; 这是一个定义,它创建了一个名为 x 的整型变量,并为其分配了内存空间,同时将其初始化为10。

在C++中,声明和定义有时可以同时发生,特别是在局部变量的情况下。例如,当你在函数内部声明一个局部变量并初始化它时,你实际上也在定义它。但是,对于全局变量或跨多个文件使用的变量,声明和定义通常是分开的,以确保正确的内存分配和链接。

此外,使用 extern 关键字可以在不定义的情况下声明一个变量。这告诉编译器变量是在程序的其他地方定义的。这种做法在大型程序中很常见,特别是当变量需要在多个源文件中共享时。一个典型的用法是在一个源文件中定义变量(如全局变量),然后在需要使用该变量的其他源文件中通过 extern 声明来引用它。

5. typedef 和define 有什么区别?

typedef#define在C++中都可以用来为类型或值创建别名,但它们之间存在一些重要的区别。

  1. 原理与处理方式:#define是预处理指令,它在预处理阶段进行简单的文本替换,不进行任何类型检查或语法检查。而typedef是C++语言的关键字,它在编译阶段处理,因此具有类型检查的功能。
  2. 作用域:#define没有作用域的限制,只要是在其之后预定义的宏,在程序的其他部分都可以使用。然而,typedef有自己的作用域,它遵循通常的C++作用域规则。
  3. 复杂类型的处理:对于复杂的类型声明,typedef能提供更加清晰和易于理解的方式。例如,对于函数指针类型,使用typedef可以使得声明更加简洁明了。而#define在处理复杂类型时可能会引发错误,因为它只是进行简单的文本替换。
  4. 调试与错误定位:由于#define是在预处理阶段进行替换的,所以如果在替换过程中发生错误,可能很难在源代码中找到错误的位置。而typedef在编译阶段处理,因此错误信息通常会直接指向源代码中的具体位置。

总的来说,typedef#define各有其用途和优点。对于简单的常量定义或简单的类型别名,#define可能更方便。但是,对于复杂的类型声明或需要类型检查的情况,typedef通常是更好的选择。在C++中,更推荐使用typedef,因为它提供了更强的类型安全性和更好的错误检查。此外,C++11引入的using关键字也可以用来定义类型别名,它在某些情况下比typedef更加灵活和易读。

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

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

相关文章

数据库表名和字段名,为什么忽略大小写?为什么采用下换线分割单词?

数据库表名和字段名,为什么忽略大小写 在数据库设计和使用中,表名和字段名的大小写敏感性是由数据库管理系统(DBMS)的配置和操作系统决定的。有些数据库系统默认是区分大小写的,而有些则不区分。 在实际操作中&#x…

docker 的网络管理

docker应用自带了三种类型的网络,然后我们自己也能自定义网络 roottest-virtual-machine:~# docker network ls NETWORK ID NAME DRIVER SCOPE 4c3e28760cff bridge bridge local afd1493dc119 host host local 5f200e2eaf22 n…

政安晨:【Keras机器学习实践要点】(六)—— 使用内置方法进行训练和评估

政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 本文涵盖使用内置 API 进行训练和验证&#…

01-DBA自学课-安装部署MySQL

一、安装包下载 1,登录官网 MySQL :: MySQL Downloads 2,点击社区版下载 3,找到社区服务版 4,点击“档案”Archives 就是找到历史版本; 5,选择版本进行下载 本次学习,我们使用MySQL-8.0.26版本…

ES6 常用知识点英文单词总结

通过记忆ES6这些关键词及其中文含义,可以帮助更好地理解和掌握ES6带来的新特性。 以下前一篇文章ES6(ECMAScript 6)中常用的知识点总结(包含示例代码)提到的ES6常用知识点的关键词及中文含义: let, const - 声明变量,常量箭头函数 - Arrow Function模板…

sonar扫描bug及对应修复

##1.Use isEmpty() to check whether the collection is empty or not. 解释: 建议使用list.isEmpty()方法 替代list.size()0 或者 !list.isEmpty() 替代 list.size() >0 修改前: if(attachedColumns.size() > 0) 修改后: if(attache…

菜鸟笔记-15arange函数学习

arange函数是Python中Numpy库的一个函数,主要用于生成一个等差数列。这个函数非常适用于创建指定范围内的数字序列,用于数值计算、数据分析等多种场景。 arange函数的语法如下: numpy.arange([start,] stop[, step,], dtypeNone) 参数说明…

机器学习 | 期望最大化(EM)算法介绍和实现

在现实世界的机器学习应用中,通常有许多相关的特征,但只有其中的一个子集是可观察的。当处理有时可观察而有时不可观察的变量时,确实可以利用该变量可见或可观察的实例,以便学习和预测不可观察的实例。这种方法通常被称为处理缺失…

vue2高德地图选点

<template><el-dialog :title"!dataForm.id ? 新建 : isDetail ? 详情 : 编辑" :close-on-click-modal"false" :visible.sync"show" class"rv-dialog rv-dialog_center" lock-scroll width"74%" :before-close&q…

Vue.js概述

一、概述 数据驱动的响应式框架&#xff0c;我们只关注Vue对象里面设置的数据即可&#xff0c;数据发生改变时&#xff0c;页面自动重新渲染 最典型的MVVM框架 二、挂载点 什么是“挂载点”&#xff1f;一个标签 作用&#xff1a;被Vue实例接收后&#xff0c;实例中设置的各…

boot整合xfire

最近换了项目组&#xff0c;框架使用的boot整合的xfire&#xff0c;之前没使用过xfire&#xff0c;所以写个例子记录下&#xff0c;看 前辈的帖子 整理下 pom文件 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot…

Java | 日期天数计算

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 编写一个Java程序&#xff0c;用于输入一个日期&#xff08;包括年、月、日&#xff09;&#xff0c;然后判断这一天是这一年的第几天。 程序需要接收一个表示日期的字符…

Python爬虫入门:从网站爬取文章内容并保存到本地文件

目录 前言 准备工作 简单爬虫实现 注意事项 爬虫伦理与合法性 总结 前言 在互联网时代&#xff0c;数据是宝贵的资源。然而&#xff0c;当需要从海量网站中抓取数据时&#xff0c;手动操作显然不切实际。这时&#xff0c;爬虫技术应运而生&#xff0c;成为我们获取数据的…

OSG编程指南<二十一>:OSG视图与相机视点更新设置及OSG宽屏变形

1、概述 什么是视图?在《OpenGL 编程指南》中有下面的比喻,从笔者开始学习图形学就影响深刻,相信对读者学习场景管理也会非常有帮助。 产生目标场景视图的变换过程类似于用相机进行拍照,主要有如下的步骤: (1)把照相机固定在三脚架上,让它对准场景(视图变换)。 (2)…

详细分析java.io.EOFException: readObject: unexpected end of file的解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法4. 彩蛋前言 以下问题涉及知识点推荐阅读 详细分析Java中的分布式任务调度框架 XXL-Job出现 Caused by: java.lang.NumberFormatException: For input string: “Error“ 解决方法(全)java框架 零基础从入门到精通的学习路线 附开…

【爬虫基础】第4讲 GET与POST请求

GET请求 GET请求是一种HTTP方法&#xff0c;用于向服务器获取&#xff08;或读取&#xff09;数据。它是Web开发中最常用的请求方式之一。对于GET请求&#xff0c;客户端向服务器发送一个HTTP请求&#xff0c;服务器返回请求的资源。GET请求通常用于获取静态资源&#xff0c;比…

c#基础-引用类型和值类型的区别

在C#中,数据类型分为两类:值类型和引用类型。 值类型:直接存储数据,分配在栈(Stack)上。常见的值类型包括基本数据类型(int, float, double等),结构体(struct),枚举(enum)等。 引用类型:存储数据的引用和对象,分配在托管堆(Heap)上。常见的引用类型包括类(cla…

记录关于智能家居的路程的一个bug___Segmentation fault(段错误)

前言 其实发生段错误的情况有很多&#xff1a; 其实在项目的开发中最有可能的错误就是①和②&#xff0c;考虑到本项目数组用的比较少&#xff0c;所以主要是考虑错误①指针的误用。 有时候错误就是那么离谱&#xff0c;声音也算是一种设备&#xff1f;&#xff1f;&#xff…

35.HarmonyOS App(ArkUI)使用父组件@Builder装饰的方法初始化子组件@BuilderParam报错

HarmonyOS App(ArkUI)使用父组件Builder装饰的方法初始化子组件BuilderParam报错 Type void is not assignable to type () > void. <tsCheck> 去掉括号()就可以了 装饰器&#xff1a; 用于装饰类、结构、方法以及变量&#xff0c;并赋予其特殊的含义。如上述示例中En…

Linux 内核工具 iptables 配置TCP/UDP端口转发(命令参考)

1、配置TCP端口转发 把本机20000/TCP端口转发到7.7.7.7:20000 iptables -t nat -A PREROUTING -p tcp --dport 20000 -j DNAT --to-destination 7.7.7.7:20000 iptables -t nat -A POSTROUTING -j MASQUERADE 2、配置UDP端口转发 把本机20000/UDP端口转发到7.7.7.7:20000 i…