C++面试题和笔试题(四)

一、intx[6][4],(*p)[4];p=x;则*(p+2)指向哪里?

  • A  X[0][1]
  • B X[0][2]
  • C X[1][0]
  • D X[2][0]

官方解释: D

int x[6][4], (*p)[4];  
p = x;

在这里,x 是一个二维数组,它有6行和4列。p 是一个指向具有4个整数的数组的指针。

当你执行 p = x; 时,p 指向 x 的第一行。

接下来,我们要考虑 *(p + 2)

在C语言中,数组名(如 x)代表其首地址。对于二维数组,它实际上是指向第一行的指针。当你对这样的指针进行加法操作时,你会跳过整行,而不是单个元素。

因此,p + 2 会跳过前两行,指向 x 的第三行。

*(p + 2) 会解引用这个指针,所以它实际上就是 x 的第三行。所以,*(p + 2) 指向 x 的第三行的首地址。

为了更直观地理解,你可以这样想象:

  • p 指向 x[0](第一行)
  • p + 1 指向 x[1](第二行)
  • p + 2 指向 x[2](第三行)

所以,*(p + 2) 就是 x[2],它指向 x 的第三行的首地址。 

自己的理解: 

假设我们有一个叫做x的大表格,这个表格有6行和4列。就像你在纸上画格子一样,每个格子可以放一个数字。

然后,我们有一个指针p,它就像一个小箭头,可以指向这个大表格的某一行。

当我们说p = x;的时候,就是把小箭头指向这个大表格的第一行。

接下来,我们要看*(p + 2)是什么意思。

想象一下,这个小箭头每次移动,不是一格一格地移动,而是整行整行地移动。所以,当箭头移动两次时,它就跳过了两行,指向了第三行。

*(p + 2)的意思就是,箭头移动两次后指向的那一行。所以,*(p + 2)指向的就是大表格的第三行。

简单说,就像你在纸上画了一个大表格,然后有一个小箭头指向第一行,当你让箭头跳两下,它就指向了第三行。这就是*(p + 2)的意思啦!

考点

这道题的考点是C语言中的指针和数组的理解

它主要考察了以下几个方面:

  1. 指针与数组的关系:在C语言中,数组名可以视为指向数组首元素的指针。对于二维数组,数组名实际上是指向第一行的指针。

  2. 指针的加法运算:对于指向数组的指针,进行加法运算时,不是按单个元素的大小来移动,而是按指针指向的整个数组或数据块的大小来移动。例如,对于指向int数组的指针,加1意味着跳过整个int大小的空间;对于指向二维数组(即数组的数组)的指针,加1意味着跳过整个一行的空间。

  3. 指针的解引用:使用*操作符可以解引用指针,即获取指针指向的值。对于指向数组的指针,解引用得到的是数组的首元素或首行的地址。

二、有关C++中为什么用模板类的原因,描述错误的是? 

  • A.可用来创建动态增长和减小数据结构
  • B.它是类型无关的,因此具有很高的复用性
  • C.它运行时检查数据类型,保证了类型安全
  • D.它与平台无关,可移值性

官方解释: C

关于C++中模板类的使用原因,我们可以逐项分析这四个选项:

A. 可用来创建动态增长和减小数据结构


这个描述并不准确。模板类主要是用于实现泛型编程,它允许程序员定义与类型无关的函数或类,然后在实例化时指定具体的类型。动态增长和减小的数据结构通常是通过使用如std::vector这样的容器类来实现的,而这些容器类内部可能会使用模板,但模板本身并不直接用于创建这样的数据结构。

B. 它是类型无关的,因此具有很高的复用性


这是正确的。模板类的主要优势之一就是它们的类型无关性。你可以为任何数据类型(包括用户自定义类型)定义模板,并在需要时实例化它们。这大大提高了代码的复用性。

C. 它运行时检查数据类型,保证了类型安全


这是错误的。模板的类型检查是在编译时进行的,而不是运行时。当你在代码中实例化一个模板时,编译器会检查你提供的类型是否满足模板的要求,并在编译阶段报告任何类型不匹配的错误。因此,模板确实保证了类型安全,但这种检查是在编译时进行的。

D. 它与平台无关,可移值性


这也是正确的。模板类在编译时被实例化为具体的类型,生成的代码与平台相关,但模板本身与平台无关。你可以在不同的编译器和平台上使用相同的模板代码,只要这些平台支持C++模板即可。这增加了代码的可移植性。

综上所述,描述错误的是选项C:它运行时检查数据类型,保证了类型安全。

自己的理解:

A. 可用来创建动态增长和减小数据结构


这个选项的意思是说,模板类可以用来创建一种特殊的数据结构,这种数据结构可以变大也可以变小,就像我们的书包一样,可以装很多东西,也可以只装一点点。但是,模板类并不是专门用来做这个的,它更多的是用来帮助我们写一些可以重复使用的代码。

B. 它是类型无关的,因此具有很高的复用性


这个选项是说,模板类就像是一个万能的工具,不管我们要处理的是数字、文字还是其他什么东西,它都可以帮忙。因为它不关心具体是什么类型,所以我们可以把同一个模板类用在很多地方,这就是它的复用性很高。

C. 它运行时检查数据类型,保证了类型安全


这个选项其实是错的。模板类是在我们写代码的时候就检查数据类型,而不是等到程序运行的时候。如果数据类型不对,它会在我们写代码的时候就告诉我们,而不是等到程序运行时才报错。

D. 它与平台无关,可移值性


这个选项是说,不管我们是在什么样的电脑或手机上使用模板类,它都可以正常工作。就像我们玩的游戏,不管是用电脑还是手机,只要游戏支持,我们都可以玩。这就是模板类的可移植性。

所以,描述错误的是选项C,它其实是在我们写代码的时候就检查数据类型,而不是运行时

考点:

  1. 模板类的定义和用途:模板类是C++中实现泛型编程的基础工具,它允许程序员定义与类型无关的代码,从而增加代码的复用性。 

  2. 模板的类型检查时机:模板的类型检查是在编译时进行的,而不是运行时。这是模板的一个重要特性,它确保了在实例化模板时,提供的类型参数符合模板的要求。

  3. 模板的可移植性:模板代码本身与平台无关,只要目标平台支持C++模板,就可以使用相同的模板代码。这体现了模板的可移植性。

  4. 模板与动态数据结构的区别:模板类虽然可以用于定义数据结构,但它本身并不直接创建动态增长和减小的数据结构。这种数据结构的实现通常依赖于特定的容器类,如std::vector等。

 三、在32位机器上用gcc编译以上代码,sizeof(),sizeof()分别是多少

Class A
{
int a;
short b;
int c;
char d;
};
class B
{
double a;
short b;
int c;
char d;
};
  •  A 12,16
  •  B 12,12
  •  C 16,24
  •  D 16,20

官方解释:C

以下是对每个数据成员的大小和可能的对齐要求的简要说明:

  • int 通常大小为4字节,并且通常需要4字节对齐。
  • short 通常大小为2字节,并且通常需要2字节对齐。
  • double 通常大小为8字节,并且通常需要8字节对齐。
  • char 通常大小为1字节,对齐要求通常最小。

现在,让我们考虑类AB的内存布局:

 对于类A

class A  
{  int a;   // 4字节,可能需要对齐到4字节边界  short b; // 2字节,可能需要对齐到2字节边界(但因为前面是int,所以这里可能不需要额外的填充)  int c;   // 4字节,需要对齐到4字节边界(这里可能需要填充)  char d;  // 1字节,通常不需要额外的对齐或填充  
};
int a (4 bytes)  
short b (2 bytes)  
填充 (2 bytes) // 为了使下一个int c对齐到4字节边界  
int c (4 bytes)  
char d (1 byte)  
填充 (3 bytes) // 为了使整个结构体的大小是4的倍数(取决于编译器是否这样做)

 总大小可能是 4 + 2 + 2 + 4 + 1 + 3 = 16 字节。

由于int之后紧跟着short,并且int已经满足了short的2字节对齐要求,所以这里可能不需要填充。但是,short之后是另一个int,这通常要求4字节对齐。如果short之后没有足够的空间来满足下一个int的4字节对齐要求,编译器可能会在shortint之间插入填充字节。

对于类B

class B  
{  double a; // 8字节,需要对齐到8字节边界  short b;  // 2字节,可能需要对齐到2字节边界(但因为前面是double,所以这里可能需要填充)  int c;    // 4字节,需要对齐到4字节边界(这里可能需要填充)  char d;   // 1字节,通常不需要额外的对齐或填充  
};
double a (8 bytes)  
填充 (6 bytes) // 为了使short b对齐到下一个合适的地址(可能是2字节边界)  
short b (2 bytes)  
填充 (2 bytes) // 为了使int c对齐到4字节边界  
int c (4 bytes)  
char d (1 byte)  
填充 (1 bytes) // 为了使整个结构体的大小是合适的对齐值(取决于编译器)

B的大小可能是 8(double) + 6(填充) + 2(short) + 4(int) + 1(char) + x(填充),其中x取决于编译器是否添加额外的填充以及添加多少。如果编译器决定让整个结构体的大小是8的倍数(以匹配double的对齐要求),那么总大小可能是24字节。

自己的理解: 

你有一个大盒子(这就是我们的结构体或类),你要把一些不同大小的东西放进去。但是,你不能随便放,有些东西需要放在特定的位置,这样拿起来才会更方便(这就是对齐的意思)。

对于类A

  1. 你首先放了一个大玩具(int a),它占了4个格子的空间。
  2. 然后你放了一个小玩具(short b),它占了2个格子的空间。因为它紧挨着大玩具,所以不需要额外的格子。
  3. 接下来,你想再放一个大玩具(int c),但是你需要确保这个大玩具从新的4个格子的位置开始放,这样拿起来更方便。所以,你在小玩具和大玩具之间放了2个空格子。
  4. 最后,你放了一个非常小的玩具(char d),只占了1个格子。
  5. 但是,为了让整个盒子的大小是4的倍数(这样放起来更整齐),你又在盒子的最后面放了几个空格子。

对于类B

  1. 你首先放了一个非常大的玩具(double a),它占了8个格子的空间,并且从8个格子的位置开始放。
  2. 接着你想放一个小玩具(short b),但是因为这个大玩具占了8个格子,你需要在大玩具和小玩具之间放6个空格子,这样小玩具才能从合适的位置开始。
  3. 然后你又放了一个大玩具(int c),它占了4个格子。这次不需要额外的空格子,因为小玩具后面已经有足够的空间了。
  4. 最后,你放了一个非常小的玩具(char d),只占了1个格子。
  5. 和类A一样,为了让整个盒子的大小是8的倍数,你又在盒子的最后面放了几个空格子。

 四、下面对静态数据成员的描述中,正确的是

  • A.静态数据成员可以在类体内进行初始化
  • B.静态数据成员不可以被类的对象调用 
  • C.静态数据成员不受private控制符号的作用
  • D.静态数据成员可以直接用类名调用

官方解释:AD

  • 选项 A:静态数据成员可以在类体内进行初始化,使用static关键字声明后,可以在类声明中直接初始化静态数据成员,例如static int val = 42;。所以选项 A 是正确的。
  • 选项 B:静态数据成员可以被类的对象调用,静态数据成员是类的所有对象共享的成员,可以通过类的对象来访问静态数据成员,例如MyClass obj; obj.val = 24;。所以选项 B 是错误的。
  • 选项 C:静态数据成员受private控制符号的作用,即使是静态数据成员,如果被声明为private,也只能在类的内部访问,例如private static int val;。所以选项 C 是错误的。
  • 选项 D:静态数据成员可以直接用类名调用,这是静态数据成员的一个重要特性,可以使用类名和点运算符来访问静态数据成员,例如MyClass.val = 64;。所以选项 D 是正确的。

 自己的理解:

  • 选项 A:静态数据成员可以在类体内进行初始化。

     

    生活例子:假设有一个人类类Person,其中有一个静态数据成员totalPopulation表示全球总人口。我们可以在类声明中初始化这个静态数据成员,例如:

    class Person {
    public:static int totalPopulation;
    };
    int Person::totalPopulation = 7000000000; // 初始化静态数据成员
  • 选项 D:静态数据成员可以直接用类名调用。

     

    生活例子:继续上面的人类类Person的例子,我们可以直接使用类名和点运算符来访问静态数据成员totalPopulation,例如:

    cout << Person::totalPopulation << endl; // 输出静态数据成员的值
     在这个例子中,我们直接使用类名Person和点运算符来访问静态数据成员totalPopulation,并将其值输出到标准输出流中。这样可以方便地获取全球总人口的信息,而不需要创建Person对象。

 考点:考察了 C++ 中类的静态数据成员的特性和使用方法,包括静态数据成员的初始化方式、访问方式以及与类对象的关系。

五、填空题(一)

#include<iostream>  
using namespace std;  class A {  
public:  A() { cout << "1" << endl; }  // 构造函数  A(const A& a) { cout << "2" << endl; }  // 拷贝构造函数  A& operator=(const A& a) { cout << "3" << endl; return *this; }  
};  int main() {  A a;   A b = a;   return 0;  
}

运行结果为( 1 ,2);

  1. 当你在 main 函数中创建 A 类的实例 a 时,会调用其构造函数,因此会输出 1
  2. 接下来,当你创建 b 并用 a 初始化它时,会调用拷贝构造函数,因此会输出 2
  • 1 对应构造函数 A()
  • 2 对应拷贝构造函数 A(const A& a)

自己的理解: 

假设我们有一个玩具工厂,这个工厂可以生产一种叫做“A”的玩具。

当我们告诉工厂开始生产一个“A”玩具时,工厂就会按照“A”的模板来制作,这就像是在代码中调用构造函数,输出“1”表示玩具制作完成了。

现在,我们已经有了一个“A”玩具,叫做“a”。如果我们想再要一个和“a”完全一样的玩具,我们不需要再让工厂从头开始制作,因为那样太麻烦了。我们可以直接让工厂复制一个“a”玩具,这样我们就得到了一个新的玩具,叫做“b”。这个过程就像是代码中的拷贝构造函数,输出“2”表示我们已经通过复制得到了一个新的玩具。

所以,整个过程的步骤和输出就是:

  1. 工厂按照模板制作了一个“A”玩具(输出“1”)。
  2. 工厂复制了一个已有的“A”玩具,得到了一个新的玩具(输出“2”)。

六、填空题(二) 

 

#include <iostream>
using namespace std
#define M(A,B,C) A*B+C
int main()
{
int a=1;
int b=2;
int c=3;
cout<<M(a+b,b+c,c+a)<<endl;
return 0;
}

运行的结果输出是(19)

官方解释

代码中定义了一个宏 M(A,B,C),它接受三个参数 AB 和 C,并将它们替换为表达式 A*B+C。这意味着在代码中每次使用 M(x, y, z) 时,它都会被预处理器替换为 x*y+z

在 main 函数中,定义了三个整数变量 ab 和 c,并分别赋值为 1、2 和 3。

接下来,代码中使用宏 M 来计算一个表达式,并将结果输出到控制台。这里,M(a+b,b+c,c+a) 会被替换为 (a+b)*(b+c)+(c+a)。将 ab 和 c 的值代入,我们得到 (1+2)*(2+3)+(3+1),即 3*5+4,最终结果为 19。

自己的理解

M(A,B,C)与M(a+b,b+c,c+a)等价的话,A=a+b,B=b+c,C=c+a;

  1. 先算a+b,也就是1加2,等于3。
  2. 再算b+c,也就是2加3,等于5。
  3. 然后根据A*B+C的例子替换为 (a+b)*(b+c),得到15。
  4. 最后加上c+a,也就是3加1,得到4。
  5. 把15和4加起来,得到最终的结果19

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

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

相关文章

鸿蒙Next学习-Flex布局

Entry Component struct FlexCase {build() {//需要在构造参数上传Flex({ direction: FlexDirection.Row,justifyContent:FlexAlign.Center }) {//flex布局Row().width(100).height(100).backgroundColor(Color.Red)Row().width(100).height(100).backgroundColor(Color.Yellow…

【DL经典回顾】激活函数大汇总(十三)(Sinc SwiGLU附代码和详细公式)

激活函数大汇总&#xff08;十三&#xff09;&#xff08;Sinc & SwiGLU附代码和详细公式&#xff09; 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里&#xff0c;激活函数扮演着不可…

使用智能型档案密集架的原因及意义是什么

智能密集架是一种具有智能化功能的存储设备&#xff0c;用于存放和管理各种物品或设备。它通常采用高度集成的设计&#xff0c;能够最大限度地利用储物空间&#xff0c;实现物品的紧凑存放。 使用专久智能智能型档案密集架的原因和意义有以下几点&#xff1a; 1. 节省空間&…

外卖平台订餐流程架构的实践

当我们想要在外卖平台上订餐时&#xff0c;背后其实涉及到复杂的技术架构和流程设计。本文将就外卖平台订餐流程的架构进行介绍&#xff0c;并探讨其中涉及的关键技术和流程。 ## 第一步&#xff1a;用户端体验 用户通过手机应用或网页访问外卖平台&#xff0c;浏览菜单、选择…

openGauss学习笔记-243 openGauss性能调优-SQL调优-典型SQL调优点-子查询调优

文章目录 openGauss学习笔记-243 openGauss性能调优-SQL调优-典型SQL调优点-子查询调优243.1 子查询调优243.1.1 子查询背景介绍243.1.2 openGauss对SubLink的优化243.1.3 更多优化示例 openGauss学习笔记-243 openGauss性能调优-SQL调优-典型SQL调优点-子查询调优 SQL调优是一…

解决安装 unbantu 后,桌面字体太小,无法调节的问题

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 一、问题描…

什么软件可以剪辑录音?录音剪辑推荐3款工具

随着数字技术的发展&#xff0c;录音已经成为我们日常生活和工作中不可或缺的一部分。无论是会议记录、课堂笔记&#xff0c;还是音乐创作、语音聊天&#xff0c;我们都需要用到录音功能。然而&#xff0c;单纯的录音往往不能满足我们的需求&#xff0c;我们还需要对录音进行剪…

C++进阶之路---手把手带你学习AVL树

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#…

HTML—CSS盒子模型(Box Model)

基本介绍&#xff1a; CSS处理网页时&#xff0c;HTML的每一个标签可以看作是一个盒子&#xff0c;网页布局将指定的标签放到指定的位置上摆放&#xff0c;相当于摆放盒子。 每一个标签(盒子)所包含的内容&#xff1a;从外到内 ①外边距(margin)—规定盒子与盒子之间的距离&…

力扣串题:反转字符串中的元音字母

​​​​​​​ 双指针&#xff0c;注意判断是否为元音的操作 bool IsVowel(char s){if(sa||se||si||so||su||sA||sE||sI||sO||sU) return true;return false; }char * reverseVowels(char * s){int len strlen(s),i0;while(i<len-1){if(IsVowel(s[i])&&IsVowel(s…

大模型训练准备工作

一、目录 1 大模型训练需要多少算力&#xff1f; 2. 大模型训练需要多少显存&#xff1f; 3. 大模型需要多少数据量训练&#xff1f; 4. 训练时间估计 5. epoch 选择经验 6. 浮点计算性能测试 二、实现 1 大模型训练需要多少算力&#xff1f; 训练总算力&#xff08;Flops&…

某鱼弹幕逆向

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018…