当前位置: 首页 > news >正文

C++入门终

目录

一、引用

二、内联函数

三、auto关键字

四、指针空值nullptr


一、引用

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

类型&引用变量名(对象名)=引用实体

	int a = 0;int& b = a;cout << &a << endl;cout << &b << endl;

这其实就是给a变量,取了一个b的别名,二者同用一块空间

接下来是引用的一些实例说明

void Swap(int& a, int& b)
{int temp = a;a = b;b = temp;
}
int main()
{int a = 0;int b = 1;Swap(a, b);
}

以前我们写Swap函数我们都需要去写指针,然后把a和b的地址传过去,但是我们用引用的话就可以和a,b同用一块空间,写起来的代码更加具有可读性和便捷;

typedef struct ListNode{int val;struct ListNode* next;
}ListNode;
void PushBack(ListNode** phead, int x)
{ListNode* newnode;if (*phead == NULL){*phead = newnode;}else{//-----}
}
int main()
{ListNode* plist = NULL;PushBack(&plist, 1);
}

这是c语言的玩法,我们在pushback的时候如果只传一个指针过去的话,那么就跟传整型一样,形参的改变并不影响实参,所以我们要传指针的地址过去,用二级指针,这样理解起来是非常费劲的;接下来我们看引用完优化的代码

typedef struct ListNode{int val;struct ListNode* next;
}ListNode;
void PushBack(ListNode*& phead, int x)
{ListNode* newnode;if (phead == NULL){phead = newnode;}else{//-----}
}
int main()
{ListNode* plist = NULL;PushBack(plist, 1);
}

这个我们就相当于给plist这个指针去取别名,函数里面的改变就会直接影响到plist

有的上面也会这样写

typedef struct ListNode {int val;struct ListNode* next;
}ListNode,*PlistNode;
void PushBack(PlistNode& phead, int x);

这种就是对结构体指针的typedef

2.引用特性

引用在定义时必须初始化

一个变量可以有多个引用

引用一旦引用一个实体,再不能引用其他实体

int main()
{int a = 0;int& b = a;int& c = a;int& d = b;
}

引用也可以是引用的别名,本质都是同一个空间

作返回值

//传值返回

int Count()
{int n = 0;n++;return n;
}
int main()
{int ret = Count();return 0;
}

出了作用域我们的n就销毁了,所以不敢拿n返回,所以会生成一个临时变量,这个临时变量可能是拿寄存器充当或者其他等等;

//传引用返回

int& Count();

返回的是n的别名,为什么返回n的别名,Count不是被销毁了吗,其实它就像你在酒店里面开了一个房间,你不用就退房了,然后你偷偷保留了一把钥匙,你也不知道这个房间里会被别人使用过还是保持原状

 这里打印的结果可能是1,也可能是随机值,具体要看编译器或者说操作系统,如果这个栈帧没有清打印的结果就是1,如果被清了,就可能出现随机值

int main()
{int& ret = Count();cout << ret << endl;cout << ret << endl;return 0;
}

这段改的意思就是你ret就是n的别名

我们流插入两次就相当于调用了两次函数,第一次我们可以调取到,但是第二次向下开辟栈帧就可能比它打或者比它小,就会对n这个变量进行覆盖,我们第二次调用的就是覆盖以后的栈帧

如果我们定义一个很大的数组的话,n在下面的话,就可能不会被覆盖,但是一般n都是在很前面的,所以会出现随机值。

注意:如果函数返回时,除了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

传引用传参(任何时候都可以)

1.提高效率

2.输出型参数(形参的修改,影响实参);

传引用返回(出了函数作用域对象还在才可以用)

1.提高效率

2.修改返回对象

struct SeqList
{int a[10];int size;
};//C的接口设计//读取第i个位置的值
int SLAT(struct SeqList* ps, int i)
{assert(i < ps->size);// ...return ps->a[i];
}/*修改第i个位置的值*/
void SLModify(struct SeqList* ps, int i, int x)
{assert(i < ps->size);// ...ps->a[i] = x;
}

这是c语言的程序设计但是我们用引用就能一个函数代码就解决了

CPP接口设计

读或者修改第i个位置的值

int&SLAT(struct SeqList* ps, int i)
{assert(i < ps->size);// ...return ps->a[i];
}
int& SLAT(struct SeqList& ps, int i)
{assert(i < ps.size);// ...return ps.a[i];
}
int main()
{struct SeqList s;s.size = 3;SLAT(s, 0) = 10;cout << SLAT(s, 0) << endl;return 0;
}

我返回数组第0个位置的别名,我修改这个别名就是在修改这个数组的值

如果不加引用呢,返回的就是临时对象,而临时对象具有常性,不能修改

接下来我们借用到一下类里面的知识

struct Seqlist
{//成员函数int& at(int i){assert(i < 10);return a[i];}//成员变量int a[10];
};
int main()
{Seqlist s2;for (size_t i = 0; i < 10; i++){s2.at(i) = i;}for (size_t i = 0; i < 10; i++){cout << s2.at(i) << endl;}
}

常引用

int main()
{const int a = 0;int& b = a;return 0;
}

这段代码是过不去的,为什么呢,举个例子,你是一个囚犯,你可以在你所在的范围内运动,但是给你取了一个别名的时候你就不是这个囚犯了吗,你就可以自由运动了吗

这本质上是权限的一种放大

在引用的过程中

权限可以平移

const int& b = a;

权限可以缩小

	int x = 0;const int& y = x;

权限不能放大

int b=a;

这个是可以的,这是一种赋值,把a的值赋值给b,b的修改并不会影响a

int main()
{int i = 0;double d = i;
}

这个是中间生成一个double的临时变量

所以改成这样子就不行了

double& d = i;

因为临时变量具有常性,跟上面举的例子是一样的

所以加const就行了

const double& d = i;

const 引用会延长这个对象的生命周期,直到你这个引用变量被销毁为止

引用和指针的区别

int main()
{int a = 0;int* p1 = &a;int& ret = a;++(*p1);++ret;return 0;
}

我们都知道指针是开空间的,但是引用开不开空间呢,引用从语法上讲是不开空间的,但从下层来看,我们通过上面的对比上可以看到,其实引用的本质就是指针

为什么那块销毁了我们还能访问它,因为引用的底层就是指针

引用和指针的不同点

1.引用概念上定义一个变量的别名,指针存储一个变量地址

2.引用在定义时必须初始化,指针没有要求

3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

4.没有NULL引用,但有NULL指针

5.在sizeof中含义不同,引用结果为引用类型的大小,但指针始终时地址空间所占字节个数(32位平台下占4个字节)

6.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

7.有多级指针,但没有多级引用 

8.访问实体方式不同,指针需要显式解引用,引用编译器自己处理

9.引用比指针使用起来相对更安全

二、内联函数

概念

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率

这个其实是补C语言宏的一个坑 

首先我们来看这个

#define Add(a,b) a+b;
int main()
{Add(1, 2);printf("%d\n", Add(1, 2));return 0;
}

宏的后面是不能加;的,因为宏是一模一样的替换到后面那个,你如果1+2;替换到下面去那么肯定是会报错的,就会变成1+2;);

#define Add(a,b) a+b
int main()
{Add(1, 2);printf("%d\n", Add(1, 2)*3);return 0;
}

这种的话优先级就有问题变成1+2*3

#define Add(a,b) (a+b)

这种的话普通场景是没有问题的但是特殊场景就会有问题了

	int a = 1, b = 2;Add(a | b, a & b);//(a | b+ a & b)

这样子+号的运算符的优先级就在其他上面

#define Add(a,b) ((a)+(b))

写成这样子才会对,我们看,宏其实是有许多缺点的

1.容易出错,语法坑很多

2.不能调试

3.没有类型安全的检查

我们写一个加法函数都比这个加法宏简单很多

优点

1.没有类型的严格限制

2.针对频繁调用小函数,不需要再建立栈帧提高了效率

C++允许把一个函数定义成内联函数

为了减少栈帧的建立,开发出了内联函数

inline int Add(int x, int y)
{return x + y;
}

特性:inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率

2.inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长),具体没有准确的说法,取决于编译器内部实现、不是递归,且频繁调用的函数采用inline修饰,否则编译器会忽略inlinetexing

3.inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到

我们在调用一个函数建立栈帧的时候就会call这个函数

内联就是在需要的地方直接展开,不会建立栈帧

func   100行

100个位置调用

是inline:10000行就是在一百个地方直接展开

不是inline:200行

不是内联这个函数就是一个调用那就是100行放在一个地方就是一个指令调用的地方只需要一行指令就可以就是call Func(0x31312),然后再jump过去,就可以调用这个函数了

所以就会引发一个问题叫作代码膨胀,就会导致你的程序变大

所以比较短的它才会展开

声明和定义分离也会出问题

它会报链接错误,它会在链接的时候根据函数名修饰规则去找这个函数的地址,找不到就会出链接错误。

但是奇怪的是这样子就可以成功了

#include "Test.h"
void f(int i)
{cout << "f(int i)" << i << endl;
}
void fx()
{f(1);
}
#include <iostream>
using namespace std;
inline void f(int i);
void fx();

我们这是间接调用的,fx()不是内联居然就可以调动的,f这个函数肯定是在的,要不然fx这个函数也不能调不到的

因为内联函数直接在使用的地方展开了,,我们就没有必要生成一堆指令建立函数的栈帧,把它们的地址放入符号表,就没有地址了

那为什么fx()能展开呢,我们仔细看看fx()既包含声明又包含它的定义,所以直接就在使用的地方展开了

所以内联函数不要声明和定义分离

有人会觉得f会不会跟别的文件里面的重合呢,就是我这个.cpp文件里面有,另一个.cpp文件里面也有,合并的时候会不会展开冲突,是不会的,因为它不生成指令,它在调用的地方就展开了;

我在其他文件里面只有声明没有定义怎么能够展开内联函数呢

三、auto关键字

int main()
{int a = 0;auto b = a;auto c = &a;auto& d = a;
}

可以自动推导类型

普通场景没有价值

类型很长就有价值,这在以后的学习以后可以知道

	std::vector<std::string>::iterator it = v.begin();auto it = v.begin();

比如说上面这么长一串代码可以简化成下面这样

auto不能推导的场景

auto不能作为函数的参数

auto不能直接用来声明数组

C++有一种东西可以帮助我们看它的类型

cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;

范围for的语法 

int main()
{int array[] = { 1, 2, 3, 4, 5 };for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)array[i] *= 2;for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)cout << array[i] << " ";cout << endl;
}

我们可以看到C读写一段数组代码是很长的

所以C++引入了范围for这种语法

for (auto e : array)
{cout << e << " ";
}

在以后的容器中也可以用到

它会依次取数组中的数据赋值给e

自行判断结束

自动迭代(++)

注意:赋值给e,改变e的值不会影响到数组里面的值,所以这就跟上面的知识串起来了我们要用到引用这种东西

for (auto& e : array)
{e *= 2;cout << e << " ";
}

注意不能用指针只能用引用,类型是不会匹配的

void TestFor(int array[])
{for(auto&e:array)cout << e << " ";
}

这个地方是不能这么玩的,范围for针对的是数组名,而你的参数却是指针

四、指针空值nullptr
void f(int i)
{cout << "f(int)" << endl;
}void f(int* p)
{cout << "f(int*)" << endl;
}int main()
{f(0);f(NULL);return 0;
}

这个实际上都会匹配到第一个去,C++把null define成0,0这个变量的值默认是整型

所以引入了nullptr这个nullptr的类型是

(void*)nullptr

C++入门就到这里结束了,下一站到类和对象,有写的不好的望大家指出

相关文章:

C++入门终

目录 一、引用 二、内联函数 三、auto关键字 四、指针空值nullptr 一、引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间 类型&引用变量名(对象名)…...

ubuntu下Qt5自动编译配置QtMqtt环境(10)

文章目录 [toc]1、概述2、下载QtMqtt源码3、编译4、验证5、参考6、视频 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt网络编程 &#x1f448; 1、概述 Qt默认是不包含mqtt库的&#xff0c;如果需要使用到mqtt库就只能自己编译配置&#xff1b; 网络所有的…...

Vulnhub DC-3靶机攻击实战(一)

导语   在之前的博客分享中,我们介绍了关于如何获取DC-1和DC-2机器的所有的Flag,下面我们来介绍一下如何对DC-3靶机进行渗透测试。 第一步、搭建靶机环境 下载靶机,并且将靶机导入到VMware环境中,如下所示。 第二步、收集服务器信息 进入到Kali攻击机之后,打开root权限…...

常用传感器介绍合集

SW-520D倾斜传感器 HX711模块&#xff1a;高精度称重的核心利器 GY302光照传感器模块详解 MLX90614红外测温传感器介绍 MAX30102心率血氧传感器模块&#xff1a;精准健康监测的利器 RGB颜色传感器简介 DS18B20温度传感器模块 人体红外传感器简介 FC-28土壤湿度传感器 …...

“为您的家电穿上防震铠甲:优质电器缓冲器

在地震频发地区或日常生活中&#xff0c;确保家电的安全和稳定至关重要。为了防止地震、意外碰撞或其他外力对家电造成损害&#xff0c;采用优质的电器缓冲器就像是为家电穿上了一层坚固的“防震铠甲”。这不仅能够有效减少因震动导致的损坏风险&#xff0c;还能显著延长家电的…...

Elasticsearch入门之HTTP高级查询操作

前言 上一篇博客我们学习了es的一些基础操作如下&#xff1a; 创建索引&#xff08;创建表 create table&#xff09;查看索引&#xff08;查看表show tables&#xff09;查看单个索引&#xff08;查看单个表show create table&#xff09;删除索引&#xff08;删除表&#x…...

Java基础-异常

异常 什么是异常 在实际工作中&#xff0c;遇到的情况不可能是非常完美的。比如&#xff1a;你写一个模块&#xff0c;用户输入不一定符合你的要求、你的程序要打开某个文件&#xff0c;这个文件可能不存在或者文件格式不对&#xff0c;你要读取数据库的数据&#xff0c;数据…...

鲲鹏麒麟使用Docker部署Redis5

本次部署采用Docker方式进行部署&#xff0c;服务器为鲲鹏服务器&#xff0c;CPU架构为ARM64&#xff0c;操作系统版本信息为 # cat /etc/kylin-release Kylin Linux Advanced Server release V10 (Tercel)镜像 下载镜像鲲鹏麒麟Redis5镜像包 部署 1、上传镜像到服务器 2、…...

家政项目小程序+ssm

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序家政项目小程序的开发全过程。通过分析微信小程序家政项目小程序管理的不足&#xff0c;创建了一个计算机管理微信小程序家政项目小程序的方案。文章…...

Day7 苍穹外卖项目 缓存菜品、SpringCache框架、缓存套餐、添加购物车、查看购物车、清空购物车

目录 1.缓存菜品 1.1 问题说明 1.2 实现思路 1.3 代码开发 1.3.1 加入缓存 1.3.2 清除缓存 1.3.2.1 新增菜品优化 1.3.2.2 菜品批量删除优化 1.3.2.3 修改菜品优化 1.3.2.4 菜品起售停售优化 1.4 功能测试 1.4.1 加入缓存 1.4.2 菜品修改 1.5 代码提交 2.缓存套餐 2.1 Spring C…...

天天 AI-241207:今日热点- Windsurf:在工程能力上进一步进化的Cursor

2AGI.NET | 探索 AI 无限潜力&#xff0c;2AGI 为您带来最前沿资讯。 Windsurf&#xff1a;在工程能力上进一步进化的Cursor 介绍了一个新的AI代码编辑器Windsurf&#xff0c;它被认为是Cursor的进化版&#xff0c;具有更强的工程能力。文章强调了Windsurf在自动化编码和系统…...

Windows远程桌面连接到Linux

我的电脑是一台瘦客户端&#xff0c;公司设置的不能安装其他软件&#xff0c;里面只有几个软件&#xff0c;还好有一个远程桌面&#xff08;Remote Desktop Connection&#xff09;&#xff0c;我想连接到另一台Linux的电脑上。 在Linux上安装xrdp&#xff1a; sudo apt insta…...

使用前,后端写 具有分页效果的数据展示

目录 前言 效果展示图如下 思路 服务器从前端界面获得什么&#xff1f; 前端界面从后端服务器应该拿到什么&#xff1f; 使用的技术 代码 前端代码 list.jsp中该功能的实现代码 后端代码 对应的servlet 代码 实体类代码 service的实现层 实现该功能的代码 dao层 实…...

ubuntu防火墙管理(六)——ebtables

ebtables 是一个用于管理以太网帧的防火墙工具&#xff0c;主要用于在数据链路层&#xff08;第 2 层&#xff09;过滤和控制网络流量。它类似于 iptables&#xff0c;但专注于以太网流量。以下是 ebtables 的基本使用方法和示例。 基本命令 ebtables 的基本命令格式如下&…...

Oracle开发和应用——常用对象(表)

6.5. 常用对象 6.5.1. 表 1)概念 表(Table),是关系库中最基本、也是最常用的数据库对象,用户的数据存储在表中,用户使用数据时可以随时通过表进行检索或操作。也可以说,表是关系库最基本、最根本的特征。我们可以通过查询系统视图来获取表的相关信息。 D:\> sqlp…...

嵌入式蓝桥杯学习8 模拟电压测量

这里本来是要讲输入捕获的知识点的&#xff0c;但是由于学校校赛时间比较紧&#xff0c;校赛没考到输入捕获&#xff0c;所以先写ADC模拟电压测量的知识点。这里将的是单通道阻塞式采样。 Cubemx配置 点开cubemx。 1.将PB15配置为ADC2-IN15。 2.在Analog中点击ADC2&#xff…...

FFmpeg源码中,计算CRC校验的实现

一、CRC简介 CRC(Cyclic Redundancy Check)&#xff0c;即循环冗余校验&#xff0c;是一种根据网络数据包或电脑文件等数据产生简短固定位数校核码的快速算法&#xff0c;主要用来检测或校核数据传输或者保存后可能出现的错误。CRC利用除法及余数的原理&#xff0c;实现错误侦…...

Android笔记【14】结合LaunchedEffect实现计时器功能。

一、问题 cy老师第五次作业 结合LaunchedEffect实现计时器功能。要求&#xff1a;动态计时&#xff0c;每秒修改时间&#xff0c;计时的时间格式为“00&#xff1a;00&#xff1a;00”&#xff08;小时&#xff1a;分钟&#xff1a;秒&#xff09;提交源代码的文本和运行截图…...

kubectl 和 kubeconfig 基本原理

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列 快捷连接 Kubernetes架构原则和对象设计&#xff08;一&#xff09; 本文介绍kubectl的几个常用命令&#xff0c;kubconfig文件基本属性&#xff0c;并开启kubectl debug日志分析其背后基本原理 …...

LVGL笔录----动画

最近在搞LVGL动画内容&#xff0c;发现网上能参考的资源太少了。现将自己学习到的内容做个笔录&#xff0c;仅供自己记录&#xff0c;若对你有帮助&#xff0c;那么最好不过&#xff0c;共勉&#xff01; 首先&#xff0c;我是在CodeBlock上仿真 #define PI 3.14159265359stat…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...