我是靠谱客的博主 有魅力戒指,最近开发中收集的这篇文章主要介绍C++后端知识库,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

编程就像马拉松,别人在你前面,永远不意味着他永远在你前面

仅以此记录秋招历程

  1. 反向问题

1. 你们部门主要负责的是什么业务,这个流程是什么样的呢?

2. 你们目前也就是现在正在研发的是什么项目可以说一下,大概一个项目周期是多久呢?

3. 你对成为一名后端开发工程师有什么建议吗?

4. 某某开发工程师的工作内容是什么,常用技能和软件

5. 测试和开发是分开的是吗?

5. 您认为我在哪些方面还存在不足

6. 请问面试官对我的职业规划的建议

  1. HR面需要了解的问题

1. 工作强度,一周几天+几点下班工作时间+加班政策

2. 公司有无福利政策,有哪些,分别是什么样的,

例如无息买房贷款,有无员工宿舍

3. 五险一金的缴纳基数,按照真实收入缴纳还是按照税前收入缴纳。

4. 五险一金的缴纳比例,单位多少+个人多少。

5. 入职以后的工作内容,常用的技能和软件等。

6. 实习期工资,实习时间

关于后端开发

  1. 软件项目开发

    目录

    个人信息

    校园实践经历

    制定学习计划

    优缺点

    抗压能力:

    关于后端开发

    软件项目开发

    流程:

    关于测试

    软件测试

    C++基础和数据结构

    计算机网络

    TCP三次握手

    TCP四次握手:

    操作系统

    360游戏服务端开发工程师一面

    如何优化链表查找的时间复杂度?

    Spring

    LRU 最近最少使用算法

    A*算法

    海康威视一面

    Tcp的接口

    TCP编程,UDP编程

    树查找的时间复杂度

    美的面试

    深信服面试:

    1. 堆和栈的应用场景:

    2. 怎么判断一个链表是否有环

    3.  实现一个string类

    4. 单链表的整表删除

    5 冒泡排序:

    6. 满二叉树和完全二叉树的区别


    流程:

1. 项目启动

确定产品方向——需求调研/市场调研——业务梳理——评审

2. 需求阶段

       提出需求——总结需求——形成需求文档

       评估开发难度、成本——评估开发工作量——项目开发计划——项目任务分解

3. 设计阶段

       (1)界面设计:

       (2)研发设计

       (3)确定总体设计

4. 开发阶段

5. 测试阶段

6. 产品上线

开发一个企业版聊天工具

后端:确认需求,该产品需要的功能,设计如何实现这些功能,确认与前端的接口(包括他发给我的消息和我发给他的消息)

  1. 后端的定义

后端其实是一堆软件

前端是从用户的角度出发,呈现在用户面前的东西都是前端,如软件界面,网页等——面向用户

我们从电子设备看到的信息和数据有一部分是存储在本地,另一部分则是由其他地方提供的,这个地方即后端。

后端是专门为前端提供数据的一套软件。

前后端如何交互:通过HTTP协议,后端程序员需要编写API接口(实现整天一次性数据传输,接口实惠随着前端页面变化的)

后端的数据放在哪里: 数据库(关系型数据库:MYSQL,非关系型数据库MongoDB)

后端开发:

在web服务器上编写软件称为web编程,不同服务器所使用的编程规范不同,通常情况下的web服务器所使用的的变成规范均为CGI变成,只能运行CGI规范的程序

CGI是公用网关接口,意思可以理解为在WEB服务器上运行一个程序或脚本,并且WEB服务器要将脚本执行结果返回给浏览器(客户端)

规范:无论使用何种语言编写,都必须使用输出函数(cout、printf)输出HTML格式的数据信息,WEB服务器根据这些信息传递给浏览器,将其先是到浏览器中,即一个WEB页面。

无论使用何种语言编写,只要在web服务器中的配置文件中,使其支持CGI编程,然后将便已完成的二进制可执行文件后缀名改为。Cgi,最后签到那页面在使用get和post方法请求这个web程序,web服务器会自动执行这个程序并将其结果送回给浏览器

  1. 客户端和服务器端

客户端(Client)是发送请求(request),服务器端(Service)是响应请求(response),返回相应的资源数据一般web的客户端就是浏览器(PC或移动设备),进行网页资源的请求,服务器响应之后返回数据,再由浏览器进行渲染。

服务器就是存放数据,文件等资源的,客户端与其进行数据的交互和数据的存储,更新。历史数据都可以保存在服器上,由云端进行保存,所以之后可以查询自己的历史记录,数据恢复,备份等。

服务器:接受请求,"读取“数据(从请求中读取需要的处理数据,从储存位置读取相关需要加工的数据...)、处理数据(逻辑加工),并将新的变更数据”写入“某个储存位置(例如:本地内存,缓存,数据库...),向客户端响应本此处理结果。

1.读取/写入:因为需要优化提高效率的缘故:会衍生出来并发,异步,其中异步需要逻辑的配合,而并发需要相关的技术(锁,队列)去处理。

2.储存位置:因为需要优化提高效率:通常会将频繁读写的数据分别储存,顺序由:二级缓存(本地内存) -> 一级缓存(redis等) -> 持久化存储(数据库),因为数据生命周期的问题需要逻辑配合,例如临时数据和持久化数据。

3.具体逻辑:需要根据具体业务去编码,同时需要配合以上两部分进行。

客户端:收集用户请求信息发送到服务器,等待服务器处理完成后将结果展现给客户。

流程:客户端实际逻辑 -> 请求发出者(浏览器,某个框架...) -> 请求接受者接受者(Tomcat服务器 ...服务器) -> 服务器具体逻辑

1.客户端实际逻辑:页面的布局显示,使用的请求协议。

2.请求发出者:当需要发出请求时,会将请求协议进一步完善,例如使用的http协议的话会将消息报头等的内容进行自动填充,然后发送给服务器

3.请求接受者:例如服务器使用的是Tomcat,此时Tomcat会将请求信息进行解析并封装成request和response对象传入service方法中,有具体继承httpServlet的Servlet类来处理。

4.服务器的具体逻辑:当Servlet(别名:Controller)类接受到服务器下发的请求时分配到具体的逻辑进行处理并响应结果。

数据库

MySQ关系型数据库

Redis、Memcached内存型数据库

  1. 为什么最好先装windows再装linux

因为linux的引导加载程序既能识别linux的核心启动文件,也能识别windows的核心启动文件;而windows的引导加载程序却不能识别linux的核心启动文件。如果先装linux的,后装windows的话,由于windows默认把引导加载程序安装在MBR(主引导扇区)与超级块中,这样的话就覆盖掉原来的linux的引导加载程序了,导致磁盘的MBR只能识别windows 的而不能进入linux了。

关于测试

测试一个水杯

寻找水杯是否有说明书,如果有说明是首先要充分阅读并理解说明是,按照说明书描述,测试所有需求点

1. 功能测试:装水,漏水,喝水,盖子,保温

2. 界面测试:外观,颜色,设计,图案是否完整

3. 易用性测试:使用水杯时是否方便,携带,防滑,水温高是是否手感不适

4. 性能测试:装水量,使用次数,保温性,耐寒性,掉落时是否可以正常使用,长时间放置是否会产生问题

5. 兼容性测试:水杯是否可以装其他液体

6. 可移植性测试:水杯放置的环境

7. 安全性测试:水杯在各种异常情况下是否会释放有毒物质等

软件测试

软件测试流程:

1. 需求分析

在测试前拿到产品需求文档,进行需求分析以及需求评审,包括产品功能点,产品核心竞争力等。

2. 测试用例设计

(1)参考软件需求规格说明书、项目总体计划,根据测试大纲制定测试用例,包括模块名、测试优先级、操作步骤、期望结果、测试结果等。

(2)举几个典型的软件测试用例:页面显示、操作功能(增删改查)、权限(身份验证、操作权限)、兼容性、扩展性、稳定性、运行速度等

3. 测试用例评审:测试为主导,联合开发、项目经理、PM进行测试用例评审

4. 测试执行:搭建环境,根据测试用例执行测试,记录测试方法和问题

5. 提交BUG并推动BUG解决

(1)根据BUG严重程度划分等级:致命、严重、一般、提示

(2)在BUG管理工具上提交BUG,详细记录测试步骤

(3)推动开发解决问题,记录问题进展

6. 回归测试

(1)对已修复的BUG进行验证,对BUG模块进行基本功能测试

(2)对整体进行冒烟测试,确保不会因为修改BUG而引起其他功能出现问题。

7. 编写并提交测试报告,并评估发布与否

8. 内测(公司内部测试)+公测(公开测试)

需求工程师:设计验证

软件测试工程师:软件测试用例

不但要有测试用例,还要有业务用例和应用用例

1. 编写一套业务数据:验证业务涉及的整体架构、业务流程、界面字段、数据关系、管控规则等,确保系统中 的业务逻辑、数据逻辑是正确的的。

2. 编写一套系统运行的脚本:这个脚本可以模拟客户的某个角色或某个流程操作的运行全过程,用以验证操作过程中每个细节是否合理、高效,让用户获得最佳的体验,包括界面布局、操作效率,智能化程度等。

C++基础和数据结构

  1. 归并排序的优缺点(稳定排序)

平均时间复杂度nlogn,最好最坏都是nlogn,额外空间复杂度n;

缺点:辅存很大,适合对象排序,

  1. Public、Protect、Private的区别

1. Public表明该数据成员、成员函数对所有用户是开放的,所有用户都可以直接进行调用;

2. Protect:对于子女朋友来说就是Public的,可以自由使用,没有限制,而对于其他外部的class来说,protect相当于private;

3.Private表示私有,即除了class自己以外,任何其他人都不可以直接使用

  1. C面向过程和C++面向对象

面向过程:是 分析解决问题的步骤,然后用函数将这些步骤一步一步实现,在使用的时候一步一步调用即可

面向对象:把构成问题的事务分解成各个对象,而建立对象的目的是为了描述某个事物在解决整个问题的过程中所发生的行为,是一种自下而上的程序设计方法,往往从问题的一部分着手,一点一点构建出整个程序。面向对象以数据为中心,类作为表现数据的工具,成为划分程序的基本单位。

  1. C++内存管理

1. 栈:存放函数的局部变量、函数参数、返回地址等,由编译器自动分配和释放;

2. 堆区:动态申请的内存空间,即由malloc分配的内存块,由程序员控制它的分配和释放,若程序执行结束还没有释放,操作系统会自动回收;

3. 全局/静态存储区(.bss段和.data段):存放全局变量和静态变量,程序运行结束操作系统自动释放。

4. 常量存储区:存放的是常量,不允许修改,程序运行结束自动释放;

5. 代码区:存放代码编译后的二进制文件,不允许修改,但可以执行

  1. 拷贝构造函数

什么时候必须重写拷贝构造函数:若需要定义一个非空的析构函数,那么,通常情况下也需要定义一个拷贝构造函数。拷贝构造函数的参数类型一般都是const

拷贝构造函数是一种特殊的构造函数,由编译器调用来完成一些基于同一类的其他对象的构建及初始化,其唯一的参数(对象的引用)是不可变的。

三种调用拷贝构造函数的情况:

(1)一个对象作为函数参数,以值传递的方式传入函数体

(2)一个对象作为函数返回值,以值传递的方式从函数返回;

(3)一个对象用于给另外一个对象进行初始化(复制);

  1. C和C++结构体的区别

(1)C的结构体内不允许有函数存在,C++允许内部有成员函数;C的结构体没有构造函数、析构函数、this指针的

(2)C的结构体对内部成员变量的访问权限只能是public,而C++允许public、protect、private三种

(3)C语言的结构体不可以继承,C++的结构体是可以从其他的结构体或者类继承过来

  1. 如果一个函数只有声明而没有定义,那么会在哪出错

答:应该是在链接阶段;编译阶段只要确认了这个函数存在并且没有错误

头文件中可以定义普通变量或函数,但是前提条件是只有一个.c或者.cpp文件包含了这个头文件,否则会发生链接错误。

目录

个人信息

1. 关于MOOS中的通信方式

2. 校园实践经历

3. 实习收获

4. 对成功的定义:

5. 职业规划

6. 制定学习计划

7. 优缺点

8. 抗压能力:

HR面需要了解的问题

关于后端开发

软件项目开发

流程:

关于测试

软件测试

C++基础和数据结构

如果一个函数只有声明而没有定义,那么会在哪出错

Vector删除和map删除的区别

计算机网络

TCP三次握手

TCP四次握手:

操作系统

360游戏服务端开发工程师一面

如何优化链表查找的时间复杂度?

Spring

LRU 最近最少使用算法

A*算法

海康威视一面

Tcp的接口

TCP编程,UDP编程

树查找的时间复杂度

美的面试

深信服面试:

1. 堆和栈的应用场景:

2. 怎么判断一个链表是否有环

3.  实现一个string类

4. 单链表的整表删除

5 冒泡排序:

6. 满二叉树和完全二叉树的区别


vector 删除和map删除的区别

vector map的区别
我们知道,vector是连续存储的数据结构,本质上是一个数组(指针确定数组的属性,如迭代器的起始和末尾,vectorsize以及capacity等)。map是一个红黑树的数据结构,关于这部分的具体内容可以查看相关的标准库。因此,树形结构的map不是连续存储的。

这两个函数都是从目标容器中删除指定元素,我们这里只讨论形参为迭代器类型的对应函数实现。

首先,mapvectorerase都会产生返回值(C++11标准,C++98map无返回值)。由我们已经预设的前提(函数形参为迭代器类型),erase操作都会返回一个指向被删除元素的下一个元素的迭代器(或者end()迭代器)。区别在于,vectorerase会破坏原有的数据存储(被删除元素的右侧元素整体向前移动),而maperase则不会破坏树的完整结构,只是删除当前结点的元素。迭代器的本质都是指针,vectormaperase都会使当前元素对应的迭代器失效,区别在于,vector的整个迭代器都会失效,而map只有当前被删除的元素迭代器失效。

计算机网络

  1. 当在地址栏输入www.baidu.com后会发生什么?(输入URL后的过程)

1. 首先浏览器向DNS请求解析主机名的IP地址;

2.  DNS会将域名解析为ip地址;

3. 浏览器通过ip地址找到对应的服务器,通过TCP三次握手,与服务器建立连接

4. 浏览器发出HTTP请求

5. 服务器收到请求后,构建所请求的web页的必须信息,返回对应的页面

6. tcp链接释放,浏览器会解析收到的文件css,js,html,img,并将web页显示给用户;

TCP三次握手

1. 当客户端想要建立连接时,他将发送一个连接请求报文,报文首部的同步位SYN置为1,和一个序列号seq假如为x。

2. 服务器的TCP收到连接请求报文后,如果同意建立连接,就向客户端发回确认,确认报文段中SYN和ACK位都为1,确认号字段ack = x+1,并且服务器产生一个起始序号seq=y;

3. 客户端收到服务器端的确认报文后,还要向服务器端给出确认,客户端向服务器端发送的报文段中的ACK标志位1,序号字段seq = x+1,ack = y+1;

成功进行以上三步之后就建立了连接。

注意:服务器端的资源是在完成第二次握手的时候分配的, 客户端的资源是在完成第三次握手时分配的。

TCP四次握手:

1. 客户端想要断开连接时,向服务端发送一个连接释放报文段,并停止发送数据,该报文段的FIN标志位为1, 序列号seq假设为u(u为前一个已经传送过的数据的序号加一);

2. 服务器端收到释放报文段后即发出确认,确认位ACK= 1,确认号ack=u+1和一个序列号seq = v(v为前面已经传送过的数据序号加一)。此时客户机到服务端方向的链接就释放了,tcp处于半关闭状态,但若服务器发送数据,客户端仍要接收。

3. 同样服务器端发出FIN=1的连接释放报文段,确认位ACK=1,确认号ack=u+1和一个序列号seq = w

4. 客户端接收到后发出确认,确认位ACK=1,确认号ack=w+1和一个序列号seq = u+1(上一步的确认号)

此时TCP连接还未释放,等待2倍的MSL(报文最大生存时间)后,才关闭连接。(等待服务器接收)。

操作系统

  1. 线程之间的通信:

1. 使用全局变量

2. 使用信号机智

3. 使用事件

  1. 进程之间的通信:
  2. 进程之间的同步

信号量,管程

  1. 什么时候用多进程,什么时候用多线程

频繁修改:需要频繁创建和销毁的优先使用多线程

计算量:需要大量计算的优先使用多线程,因为需要消耗大量CPU资源且切换频繁,使用多线程更好一点

相关性:任务间相关性比较强的用多线程,相关性比较弱的用多进程,因为线程之间的数据共享和同步比较简单。

多分布:可能要扩展到多几分不的用多进程,多核分布的用多线程。

360游戏服务端开发工程师一面

为什么想做游戏开发

因为觉得游戏开发比其他开发工作更有意思一些,而且由于我在实验室所做的工作是水下机器人的路径规划,我认为这跟游戏里面的游戏人物的移动路径也比较相关,所以就对游戏开发比较感兴趣。

如何优化链表查找的时间复杂度?

使用跳表:通过对链表加多级索引的机构,就是跳表了。

删除操作的话,如果这个结点在索引中也有出现,我们除了要删除原始链表中的结点,还要删除索引中的。因为单链表中的删除操作需要拿到要删除结点的前驱结点,然后通过指针操作完成删除。所以在查找要删除的结点的时候,一定要获取前驱结点。当然,如果我们用的是双向链表,就不需要考虑这个问题了。

如果我们不停的向跳表中插入元素,就可能会造成两个索引点之间的结点过多的情况。结点过多的话,我们建立索引的优势也就没有了。所以我们需要维护索引与原始链表的大小平衡,也就是结点增多了,索引也相应增加,避免出现两个索引之间结点过多的情况,查找效率降低。

跳表是通过一个随机函数来维护这个平衡的,当我们向跳表中插入数据的的时候,我们可以选择同时把这个数据插入到索引里,那我们插入到哪一级的索引呢,这就需要随机函数,来决定我们插入到哪一级的索引中。

Spring

Spring是目前主流的 Java Web 开发框架,是 Java 世界最为成功的框架。该框架是一个轻量级的开源框架,具有很高的凝聚力和吸引力。

LRU 最近最少使用算法

LRULeast Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。

最近最少使用算法(LRU)是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。该算法的思路是,发生缺页中断时,选择未使用时间最长的页面置换出去。 [1]
 从程序运行的原理来看,最近最少使用算法是比较接近理想的一种页面置换算法,这种算法既充分利用了内存中页面调用的历史信息,又正确反映了程序的局部问题。利用 LRU 算法对上例进行页面置换的结果如图1所示。当进程第一次对页面 2 进行访问时,由于页面 7 是最近最久未被访问的,故将它置换出去。当进程第一次对页面 3进行访问时,第 1 页成为最近最久未使用的页,将它换出。由图1可以看出,前 5 个时间的图像与最佳置换算法时的相同,但这并非是必然的结果。因为,最佳置换算法是从向后看的观点出发的,即它是依据以后各页的使用情况;而 LRU 算法则是向前看的,即根据各页以前的使用情况来判断,而页面过去和未来的走向之间并无必然的联系。

A*算法

A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是许多其他问题的常用启发式算法。从起点开始,首先遍历起点周围邻近的点,然后再遍历已经遍历过的点邻近的点,逐步的向外扩散,直到找到终点。在执行算法的过程中,每个点需要记录达到该点的前一个点的位置 -- 可以称之为父节点。这样做之后,一旦到达终点,便可以从终点开始,反过来顺着父节点的顺序找到起点,由此就构成了一条路径。

       A*算法通过f(n) = g(n) + h(n)这个函数来计算每个节点的优先级。A*算法在运算过程中,每次从优先队列中选取f(n)值最小(优先级最高)的节点作为下一个待遍历的节点。g(n)表示从初始结点到任意结点n的代价,h(n)表示从结点n到目标点的启发式评估代价(启发函数可以是曼哈顿距离、欧几里得距离)。当从初始点向目标点移动时,A*权衡这两者。每次进行主循环时,它检查f(n)最小的结点n,。

A*算法使用两个集合来表示待遍历的节点,与已经遍历过的节点,这通常称之为open_setclose_set

在极端情况下,当启发函数h(n)始终为0,则将由g(n)决定节点的优先级,此时算法就退化成了Dijkstra算法。

海康威视一面

Tcp的接口

TCP编程,UDP编程

树查找的时间复杂度

美的面试

      

物理层:

     集线器、中继器

数据链路层:

    网桥、交换机

网络层:

    路由器

传输层与之上的层:网关

JAVA语言中定义了8种基本的数据类型,来保存变量。JAVA要求程序中的每一个变量都规定自己的类型。正因为如此,JAVA属于强类型语言,从而不同于JavaScript这样的弱类型脚本语言。

  下面我们来看看这8种类型: 

byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。

short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。

int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。

long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。

float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。

double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。

boolean:只有true和false两个取值。

char:16位,存储Unicode码,用单引号赋值。

Object 是引用数据类型,只申明而不创建实例,只会在栈内存中开辟空间,默认为空,空占1 bit.

注:一个字节=8位。

int (*n)[10]

n先与*结合,所以,n是一个指针,既然是一个指针,而且是在32位操作系统下,那么n就占32位,4个字节。64位操作系统占8个字节?

深信服面试:

1. 堆和栈的应用场景:

栈是一种运算受限的线性表,其限制是指只仅允许在表的一端进行插入和删除操作,这一端被称为栈顶(Top),相对地,把另一端称为栈底(Bottom)。把新元素放到栈顶元素的上面,使之成为新的栈顶元素称作进栈、入栈或压栈(Push);把栈顶元素删除,使其相邻的元素成为新的栈顶元素称作出栈或退栈(Pop)。这种受限的运算使栈拥有“先进后出”的特性(First In Last Out),简称FILO。

堆是一种常用的树形结构,是一种特殊的完全二叉树,当且仅当满足所有节点的值总是不大于或不小于其父节点的值的完全二叉树被称之为堆。堆的这一特性称之为堆序性。因此,在一个堆中,根节点是最大(或最小)节点。如果根节点最小,称之为小顶堆(或小根堆),如果根节点最大,称之为大顶堆(或大根堆)。

堆的插入:将一个新元素插入到表尾,即数组末尾时,如果新构成的二叉树不满足堆的性质,需要重新排列元素

堆的删除:堆排序中,删除一个元素总是发生在堆顶,因为堆顶的元素是最小的(小顶堆中)。

堆的应用:  堆排序(Heapsort)是堆的一个经典应用,

2. 怎么判断一个链表是否有环

3.  实现一个string类

4. 单链表的整表删除

先将第一个节点q->next赋值给p,  释放第一个节点q, 再令q = p; 循环。(原理:在释放一个节点之前,要先将它的后继结点保存下来再释放,否则无法释放后继结点)

5 冒泡排序:

for(int i = nums.size()-1; i>=0; i++)

{

      for(int j = 1; j<=i;  j++)

      {

             if (nums[j] < nums[j-1])

                   swap(nums[j], nums[j-1]);

      }

}

6. 满二叉树和完全二叉树的区别

满二叉树:所有节点的度要么为0要么为2,且所有的叶子节点都在最后一层。深度为k,节点数量为2^k -1;

完全二叉树:树中所含的n个节点与满二叉树中的前n个节点一一对应。叶子节点只会出现在最后两层,并且最后一层的叶子节点向左对齐。

完全二叉树从根节点到倒数第二层是一棵满二叉树,满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。

最后

以上就是有魅力戒指为你收集整理的C++后端知识库的全部内容,希望文章能够帮你解决C++后端知识库所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(72)

评论列表共有 0 条评论

立即
投稿
返回
顶部