一个人找另一个人,一句话找另一句话。知道你喜欢仪式感,本想和你一起度过漫长岁月,可惜没能如愿,并不是每一次主动伸出手都能和解呢。记得和你一起去漠河看到的初雪,记得和你在呼伦湖的牵手,记得和你去长春见熊黄黄,记得和你一起去成都拍摄大熊猫,记得我们一起漫步大海边,记得我们一起爬上了角山长城,记得我们曾经在一起的时光,那个时候我们真的互相喜欢过吧。当你参加高考考数学时我在上《离散数学》,我有给你祈祷啊!等待考上一个大学,后来没有实现。大学时等待每周的见面,那是17km的距离。每个早上醒来睡眼朦胧的拿起手机,隔着冰冷的屏幕想知道你睡得好不好。现在分开了,不知道该等什么了…也在想如果你是对的人,也许还会回来,只要是对的,哪怕晚一点,我可以等。想想真是有意思,人和人之间原来是这么熟悉起来的,不知道什么时候就开始习惯你在的生活了,没什么特殊的原因,只因为一起呆得久了。后知后觉可不是什么好东西,很多时候当你觉得事情不太对的时候其实已经无法挽回了。大家都是普通人,这些年爱也爱得乱七八糟的,恨也恨得乱七八糟的,可那又有什么办法呢。。。有些事情如果你做错了的话,自己也会厌弃自己的啊,曾经以为命运是能改的,我不信命!到头来却也只能认命,我爬不动了,不会再这么固执下去了吧。有些事,你改变不了,只能怨天尤人,想象总是美好的,命中注定的事,早点轮回吧,原来这就是自己,一个普普通通的家伙,仔细想想,我这辈子努力去做的事情好像都做错了,连死死抓住那么一点点小温馨都做不到,你就该静静地呆在没人知道的地方,静静地生长也静静地枯萎,像一株野蒲公英那样,最后留在记忆深处的总是些虚无缥缈的东西。以后啊,你还可以拿起相机拍摄你最爱的东西,你还可以一路走走逛逛吃遍全国,你还可以看着你最爱的吃播视频,你还可以天天和我分享着你的所见所闻,到你身边已经没有我的位置了。过了那么久,还是要来了,只能说有缘无分吧,认识你真的很开心,谢谢你,这段日子真的特别特别高兴,在遇见你之前,这个世界上没有值得我珍视的人,我孤立着一切,只想靠自己摆脱孤独,却堕落在无尽的深渊中,我活在彻头彻尾的寒冬中。认识你之后,夏天来了,那几年我的生活充满了阳光,我有了女朋友,有了奋斗的目标,心怀未来。第一次体会到原来自己的一举一动在另外一个人的世界里都是那么重要,她会闷不作声地跟着你走,就像你的尾巴一样,从未有过这么一个人那么需要你,你怎么能看着她消失呢?那时你在我心里是最重要的人啊,世界上只要有你,每一天都是幸福的,世界上只要有你,再大的困难我也能抗,这是我一生里最开心的时间,以前没有过,以后也不会有。往往就是这样,因为告别的时候忘了约定再见的时间,从此就天各一方,但如果他喜欢你,是会追着你到天涯海角的,在一个夏天夜晚,我失去了你,连带着光荣和梦想,我仿佛再度踏入了寒冬,我并不是什么大人物,我一样需要温暖,如果有温暖,我可以庸庸碌碌地活下去,我仍然能记起那种失去你再度陷入孤独的痛苦,很多人会轻易地说出放弃二字,只是因为他们并不懂我的过去。人一生能有多久,能拥有多少东西?以后啊,不要做会让自己后悔的事,不要让那些爱你的人难过,因为这个世界上,你爱的人固然很少,爱你的人也绝不会多。想努力把那两年人生扔进垃圾堆,觉得那是错误的时光,再也不愿回想,仔细想想,其实那两年里也有很多的好事情不是么?

2016-09-09 和你初次见面 余生多多指教

2016-09-15 心急的跑去你们学校 第一次去你们学校 差点走错了路 迷茫的走到了哈尔滨北站 不管过程如何 能见到你就很开心啦 这天是中秋节 月亮很圆 离别的时候差点忘了给你月饼 还好回头望你的时候想起来了 把所有月饼都给你了 只想把身心一切都掏给你

2016-09-30 和你错过了去齐齐哈尔的火车 但和你在一起我就很开心

2016-10-01 和你到达齐齐哈尔 前往漠河 傍晚火车上的风景真美 很想和你再体验一次

2016-10-02 和你去漠河 认识了一对北京的情侣 遇到了一个很好的大叔司机

2016-10-03 和你一起看漠河的初雪 太美了 漠河的一切都像一场美梦 我们买了两个套娃 一人一个

2016-10-05 和你去了满洲里婚礼宫 晚上的满洲里就是一座灯光的城堡

2016-10-06 和你去满洲里国门 套娃广场 呼伦湖 在呼伦湖牵手了

2016-10-07 和你去了哈尔滨索菲亚教堂 有人说”从他打的伞可以看出是真爱”

2016-11-12 和你去长春见到了台灯和熊黄黄 熊黄黄和你说看得出来我很喜欢你

2016-11-13 和你吃了黄焖鸡米饭 去了伪满洲国皇宫

2017-01-05 和你去了长沙五一广场 一起吃了很多东西

2017-01-06 和你去了橘子洲头 可惜没看到橘子洲头的烟花

2017-01-07 和你去湘潭湖南科技大学见了我的好朋友

2017-02-24 和你还有春香在武汉转车回哈尔滨 吃了武汉热干面 你们去看了电影

2017-04-01 你和春香去师大夜市 此刻我在上信息检索课 下课后我一路上跑啊跑 终于在师大夜市找到了你

2017-04-14 坐夜班公交车的人都很有很有故事 你室友又不懂你为何又一次急着来见我 因为你太想我了 此刻我也很想你 只有见到彼此才能把互相的心填满 我们一起去了滨江大桥 夜景的哈尔滨真是太美了

2017-04-20 黄焖鸡米饭 “待宝宝学会给你做”

2017-04-29 和你在沈阳

2017-04-30 沈阳

2017-05-01 和你一起去东北大学见到了春晚哥 我下棋输给了他

2017-05-05 你和春香一起来黑大夜市

2017-05-06 你来和我一起看房 我们在新主楼发现一个不错的房子 就去看了 租下来了

2017-05-07 你和我去服装城买被子 因为错过了时间一起淋了一场雨 签好了合同 我们有一个小家啦

2017-07-11 考完了最后一门 我们一起坐火车去成都

2017-07-13 早上我们到了成都站 休息了一会儿我们就去了武侯祠 锦里 在春熙路见到了小疼疼

2017-07-14 去了大熊猫基地 在环球中心一起等到了墨想 一起去广都站那边吃火锅 小疼疼也来了 一起去了墨想家 晚上你买了一副墨镜

2017-07-15 我们和墨想一起去了水上乐园 见到了仰慕豪和黑骑之魂 黑骑之魂被蚊子咬得好惨 我们一起打了乒乓球 我们5个还去仰慕豪家玩了奇怪的一种牌

2017-07-16 我们起晚了 我买了回家的无座 最后我在成都东站等你 没有上回家的火车 我们一起去了南充 我见到了北邮的SC哥哥 在南充转车去岳池 你好朋友过生日 你把我的箱子放在你家 你婆婆看到了我的背影 我一个人在岳池一中逛 走过你生活的校园 最后躺在足球场 太阳落山了 有点孤单 被一个小孩子用足球踢到了眼镜 他家长把他带走了 我等啊等 终于等到了你 你居然带我去了你家 见到了你姐姐 还吃到了你给我下的面 很幸福啊 半夜我们跑出去吃冰粉 走了好远好远到达时代酒店 4点多 天还没亮 你怕你婆婆发现你不在家 又打车回家了 发消息给我让我不要担心你

2017-07-17 我们一起去吃了冰粥 打包了一份炒河粉 一起去了你经常去的电影院坐着 最后一起去岳池站 那天火车晚点了很久 我们从5点等到8点多 临走前你还怕我挨饿给我买了很多吃的 我9点多到重庆北站转车踏上了回家的路

2017-08-25 你来哈尔滨站接我回我们的小家

2017-09-09 在一起一周年啦 我们发现了一家重庆小面 那儿有我最爱的冰粉

2017-09-28 看完巴萨的欧冠之后 我就出发啦 你的手机屏幕不小心全部摔碎了 我走到了哈尔滨西站 乘上了最早的一班动车 在你学校图书馆门口和你相见 把我的小米2S借给你用 一起去吃了早餐 等你上完早自习我们又在一起待了一会儿 我好舍不得离开你啊 但是你要上课 我也要上课 你去上课后我跑去哈尔滨北站坐动车到哈尔滨西站 遇到拉肚子在厕所上了个厕所 上了31路公交车 堵车堵车堵车 10:10才到学校门口 一路飞奔去新主楼 只迟到了几分钟 是陈宜冬老师的网络设备课 课上几乎睡了过去 下课后就直接回去睡觉啦

2017-09-30 早上我去上课 我的Macbook 你的iPhone6s都到啦 晚上出发前往大连 车上遇到有人打架

2017-10-01 我们在大连站外面走丢了 我在原地等你 终于等到了你 后来吵架了 你上公交车 我没零钱没上 可是你给我投钱了 我不知道 像个孩子一样蹲在地上难过 你在下一站下车跑过来找我 你对我真好 美团意外的丢失了订单 我们找错了酒店 折腾了一上午 下午我们睡了一下午 晚上醒来的时候随便吃了点东西 一起玩王者荣耀玩到很晚

2017-10-02 我们都是第一次见到大海 在大连的星海公园 拍了很多海景照 你真可爱 下午我们去了大连的威尼斯水城 找到了猫的天空之城那家书店

2017-10-03 我们去金州站坐火车 只买了到大石桥的火车 补票到北戴河站 吃了烧烤 还在北戴河的刘庄那条街溜达了很久

2017-10-04 上午一起去爬了联峰山 下午一起去了老虎石海上公园 你在沙滩上写了蓉蓉兔生日快乐 写了王紫欣 写了帆帆i love u 你说甜六度苦四分

2017-10-05 清早踏着朝阳我们去了鸽子窝公园 你的手机掉了 好在遇到了好心人失而复得 一起喝了老北京酸奶 中午我们坐动车从北戴河到了山海关 下午我们去看了天下第一关 爬了角山长城 在山上遇到了老外问我问题 我让你和他交流 好像问的山顶上是什么 以及有多远 晚上 我们踏上了回哈尔滨的火车 火车上遇到两个俄罗斯人

2017-10-07 我的20岁生日 我们去吃了自助餐 你买了可妮兔和布朗熊的蛋糕送我 最快乐的一个生日有你陪我

2017-12-28 你和春香从哈尔滨飞回重庆了 感觉哈尔滨只剩下我孤零零的一个人了

2018-02-28 科目二挂了 但是有你在 所以不可怕 我下次一定要考过

2018-03-04 努力转车 只为离你近一点 早上我终于在哈尔滨西站见到了你 虽然哈尔滨还被冰雪覆盖着 但我心里暖暖的 然后各回学校

2018-03-09 想给你更好的生活 我决定去金山赚钱 买了好几本面试的书 努力努力再努力

2018-04-15 飞往长沙 参加金山春招长沙站笔试 那一周我是无比的想念你

2018-04-22 飞回哈尔滨 终于回到了你在的城市

2018-04-28 得到了金山HR的3面通知 和你去黑大夜市吃东西 还买了我们都喜欢的西米露

2018-05-03 收到了金山的正式实习offer 努力就是有结果的啊 因为有你在 所以我得变优秀 为我们创造更好的未来

2018-05-04 你陪我去办了银行卡作为工资卡

2018-05-11 抽血 我最怕了 但是抽完血就能见到你啦

2018-05-12 汶川大地震十周年 你的手机外屏碎了 我们一起去给你手机换外屏 然后吃了韩盛烤肉 吃得很撑

2018-05-14 拿到了体检报告 身体有点小问题 为了你 我得好好注意自己的身体才行

2018-05-18 很想把你介绍给Final,老司机,小帅,还有海绵宝宝,但是你好像不太想,我就和他们去吃火锅告别,回来得很晚

2018-05-19 和你一起去找吉他包装 遇到了好心人把外包装免费送给我们 把我送你的吉他寄回了你家 在黑龙江省京剧院旁边的那个桥上对你发火了 把雪碧狠狠地摔在地上 对不起 我没控制好自己的情绪 你一定对我非常失望吧

2018-05-20 520 下午把大部分东西都寄走了 祝贺RNG夺得了MSI冠军

2018-05-21 离开哈尔滨 前往金山 相同的分别地方 相同的大叔 不敢看此刻的你 我哭了

2018-05-22 到达金山,金山很棒

2018-06-12 被训话了 我真差劲

2018-06-15 下班后马上出发 没有买票就到了唐家湾站 努力努力再努力 只为能在你20岁那天见到你 幸运的买到了想去的行程 珠海-广州-岳阳-武汉-哈尔滨

2018-06-17 终于见到你啦!我们去吃了上次没吃成的那家鱼 宝贝20岁生日快乐!

2018-06-22 考完晚上一门的我见到了你

2018-06-23 我们去了韩盛烤肉 去逛了松雷商业大厦 到处都是世界杯的主题

2018-06-24 我们去了哈理工 又去了你学校 时隔那么久我终于又去了你学校 我很喜欢你学校 更喜欢你学校的你 我们在玩吃鸡 还遇到一对很可爱的男孩子 游戏只是娱乐 然后我们都饿了 一起去杉杉奥特莱斯吃逃课吃串串 我最喜欢成都风格的美食了 也很喜欢成都这座城市 最后我们经过了哈师大 回到了你学校 你最好了 最后我们还是分别了 你想送我 我怕你一个人危险 让你回去了 离开你学校 突然泪目 我不知道我什么时候还能来你学校

2018-06-25 忍不住去了你学校 可是你在写论文太忙了 我在你学校逛了好久好久 多么希望能够见到你的背影啊

2018-06-27 回珠海了 我会想你的

2018-07-03 终于凑够了钱可以送你一台你最想要的ipad啦 下一个目标 带你去jay或者eason的演唱会

2018-07-18 被告知被解雇了 你一直在安慰我 很想抱着你埋头痛哭 此刻的我很脆弱

2018-07-20 正式离职 不知道未来会如何 但我应该会找到下一份工作吧

2018-07-24 分手

2018-07-26 未知的未来 可是我别无选择 想去找你 可是你不愿意见我

2018-07-27 一个人坐在空空的车厢里,听着布拉格广场,望着逐渐变黑的天空,心里特没底,你现在会在干嘛呢?

2018-07-28 我逃到了成都 这是一个好地方 但我没有心安 我失败了

2018-10-01 国庆节你来探望了我一下午,晚上我们在足球场谈了很多,分别的时候你还送了我一盒酸奶,你让我失去了自我,为了你,我好像把原来的那个我完全抛弃了。不知道自己是对还是错,我这样做只是为了你,我很怕失去你,你讲几句重话,我就手足无措了,这样的我,我简直觉得不可思议,我简直有点轻视我自己了,太没出息了。

2018-10-04 我们一起去KTV唱歌啦!你还送了我一个生日蛋糕,超开心超开心的!最后很舍不得分别,眼看你越走越远,我的心似乎跟着你一起走了,想到此后,我每天会在无尽的相思里度过,我就不寒而栗了,但愿我能把每一丝每一缕的相思织成天罗地网,网住你,保护你,让你不会受到伤害。记住,要保护自己,因为我在等你,等你,等你。

2018-10-13 你约我晚上出来散步,开心,坐下来写下这些字的时候,我才明白是给自己心里写的一个安慰。
很开心的是,此刻我还有时间写下自己的心情,让自己开心一点。
最近一段时间,对我来说是一个十足的低谷,身体、学业、爱情、工作,还有心理,所有的这一切都是自己一手造成的。
直到现在我才知道自己不是一个聪明的人,其实最笨的人才是自己,很笨很笨的那种,丢失了最爱的人,丢失了曾经的梦想,丢失了最珍贵的一切。
不过还是要说:所有的苦难都将是一笔财富。

2018-11-03 陪你去考了一天的教师资格证,一起逛了商场,给你拍了照,在商场里的书店里发现了你超喜欢的猫王收音机,好贵好贵啊,等我有钱了一定送你一个,慢慢发现和你分手已经三个多月了,这漫长的三个月,对我像漫长的三个世纪,每一天怎么活过来的,自己都弄不清楚,你的冷漠让我痛彻心扉,我整天关在家里,不能思想,不能分析,脑子里一片空白与麻木,午夜梦回,我在窗边呼唤你的名字,一遍又一遍,一次又一次,直到天亮了,你说的那些话,每一字每一句,就像一把锐利的刀,切割着我的全身,千言万语我只想和你说一句话,我爱你,全心全意的爱着你。

(未完待续)

你最好了。

 

原地址:https://weibo.com/ttarticle/p/show?id=2309404275311117213990

1.创建远程仓库。

Project name:项目名称

Project description (optional):项目介绍

Visibility Level :项目的访问权限

2.创建完成后操作,终端cd 到你需要克隆到的文件夹目录下:

a. cd <你本地文件夹目录>

b.git clone <你自己刚创建的远程仓库目录>

c.把代码导入你clone 下来的目录下

3.提交代码

a. git add *

b.git commit -m”<注释>”

c.git push origin master

以上就是简单的代码上传过程。

注:你自己也可以在终端创建远程仓库

4.打开git命令窗口:
git clone 远程代码仓库的地址
cd (git clone的文件夹路径)

git pull origin master//更新 必须做的操作

// git remote add origin 你刚才建立的项目连接
git add .
git commit -m ‘注释’
git push -u origin master 将代码推送到gitlab端

5,创建并切换分支本地分支并推送到远程服务器;

git branch : 查看我们的git仓库有几个分支,而我们目前工作处于那个分支,前面有个*号的就为我们目前所处的分支。

git branch -a : 查看远程分支。

git branch name : 创建分支,而这个分支的指针就指向最新的commit对象,也就和HEAD指向同一对象。如git branch test,表示创建本地test分支。
git checkout name : 切换到目的分支,我们默认的主分支为master。
git checkout –b name:创建并切换分支。
git push origin name: 将本地name分支推送到远程服务器。

git status : 查看文件更改状态。在添加文件之前或之后,我们会用git status 查看有变化的文件(一般有变化的文件会以红色显示出来)。

//设置显示隐藏文件夹
defaults write com.apple.finder AppleShowAllFiles YES

6,遇到的问题,即解决办法:
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to ‘git@github.com:******/Demo.git’
hint: Updates were rejected because the tip of your current branch is behind

1.使用强制push的方法:

$ git push -u origin master -f

这样会使远程修改丢失,一般是不可取的,尤其是多人协作开发的时候。

2.push前先将远程repository修改pull下来

$ git pull origin master

$ git push -u origin master

3.若不想merge远程和本地修改,可以先创建新的分支:

$ git branch [name]

然后push
$ git push -u origin [name]

方法一很暴力,但很实用,可以轻易本地文件同步到远程服务器端。
多人协作使用,慎用!

7.tag 的简单使用

1. git push –tags 把本地的tag推送到远程

2.git fetch origin tag <tagname> 获取远程tag

Qt官方信息

  • Qt官网:http://qt.digia.com/
  • Qt开源官网:http://qt-project.org/
  • Qt最新版本下载:http://qt-project.org/downloads
  • Qt所有版本下载:ftp://ftp.qt-project.org/qt/source/
  • Qt Creator所有版本下载:ftp://ftp.qt-project.org/qtcreator/

Qt与Qt Creator简介

Qt是一个跨平台应用程序和 UI 开发框架。使用 Qt 您只需一次性开发应用程序,无须重新编写源代码,便可跨不同桌面和嵌入式操作系统部署这些应用程序。

Qt Creator 是全新的跨平台Qt IDE,可单独使用,也可与 Qt 库和开发工具组成 一套完整的SDK. 其中包括:高级 C++ 代码编辑器,项目和生成管理工具,集成的上下文相关的帮助系统,图形化调试器,代码管理和浏览工具。

Qt功能与特性

  • 直观的 C++ 类库:模块化 Qt C++ 类库提供一套丰富的应用程序生成块 (block),包含了构建高级跨平台应用程序所需的全部功能。具有直观,易学、易用,生成好理解、易维护的代码等特点。
  • 跨桌面和嵌入式操作系统的移植性:使用 Qt,您只需一次性开发应用程序,就可跨不同桌面和嵌入式操作系统进行部署,而无须重新编写源代码,可以说Qt无处不在(QtEverywhere) 。
  • 使用单一的源代码库定位多个操作系统;
  • 通过重新利用代码可将代码跨设备进行部署;
  • 无须考虑平台,可重新分配开发资源;
  • 代码不受担忧平台更改影响的长远考虑 ;
  • 使开发人员专注于构建软件的核心价值,而不是维护 API 。
  • 具有跨平台 IDE 的集成开发工具:Qt Creator 是专为满足 Qt 开发人员需求而量身定制的跨平台集成开发环境 (IDE)。Qt Creator 可在 Windows、Linux/X11 和 Mac OS X 桌面操作系统上运行,供开发人员针对多个桌面和移动设备平台创建应用程序。
  • 在嵌入式系统上的高运行时间性能,占用资源少。

Qt Creator功能和特性

  • 复杂代码编辑器:Qt Creator 的高级代码编辑器支持编辑 C++ 和 QML (JavaScript)、上下文相关帮助、代码完成功能、本机代码转化及其他功能。
  • 版本控制:Qt Creator 汇集了最流行的版本控制系统,包括 Git、Subversion、Perforce、CVS 和 Mercurial。
  • 集成用户界面设计器:Qt Creator 提供了两个集成的可视化编辑器:用于通过 Qt widget 生成用户界面的 Qt Designer,以及用于通过 QML 语言开发动态用户界面的 Qt Quick Designer*。
  • 项目和编译管理 :无论是导入现有项目还是创建一个全新项目,Qt Creator 都能生成所有必要的文件。包括对 cross-qmake 和 Cmake 的支持。
  • 桌面和移动平台:Qt Creator 支持在桌面系统和移动设备中编译和运行 Qt 应用程序。通过编译设置您可以在目标平台之间快速切换。
  • Qt 模拟器:Qt模拟器是诺基亚 Qt SDK的一部分,可在与目标移动设备相似的环境中对移动设备的 Qt 应用程序进行测试。

Qt的历史

  • 1996年Qt 上市
  • Qt 已成为数以万计商业和开源应用程序的基础
  • Qt 的软件授权机制具有经受市场检验的双重授权(开源与商业)模式
  • Qt Software 的前身为 Trolltech(奇趣科技)。 Trolltech (奇趣科技)始创于1994年
  • Trolltech (奇趣科技)于2008年6月被 Nokia 收购,加速了其跨平台开发战略
  • 2012年8月芬兰IT业务供应商Digia全面收购诺基亚Qt业务及其技术

Qt所支持的平台

1.嵌入式 Linux (Embedded Linux)

Qt for Embedded Linux® 是用于嵌入式 Linux 所支持设备的领先应用程序架构。您可以使用 Qt 创建具有独特用户体验的具备高效内存效率的设备和应用程序。Qt 可以在任何支持 Linux 的平台上运行。Qt 的直观 API,让您只须少数几行代码便可以更短的时间实现更高端的功能。

特点:

(1) 用于Linux 的紧凑的视窗系统;

(2) 用于广泛的应用程序处理器的开发;

(3) 移植桌面代码至嵌入式平台,或通过重新编译,反之亦然;

(4) 编译移除不常使用的组件与功能;

(5) 利用系统资源并实现本地化性能;

(6) 开发嵌入式设备犹如开发桌面系统一样轻松简单。

Qt 除了提供所有 工具 以及 API 与 类库 ,( 如WebKit ) 外,Qt for Embedded Linux 还提供用于最优化嵌入式开发环境的主要组件。

  • 紧凑高效的视窗系统 (QWS):Qt 构建在标准的 API 上,应用于嵌入式 Linux 设备,并带有自己的紧凑视窗系统。基于 Qt 的应用程序直接写入Linux 帧缓冲,解除了您对 X11 视窗系统的需求。具有减少内存消耗,占位更小,可利用硬件加速图形的优势,可编译移除不常使用的组件与功能等特点。
  • 虚拟帧缓冲 (QVFb):Qt for Embedded Linux 提供一个虚拟帧缓冲器,可以采用点对点逐像素匹配物理设备显示。具有真实的测试构架,在桌面系统上嵌入式测试,模拟物理设备显示的宽度、高度与色深等特点。
  • 进程间通讯 (IPC) :IPC (进程间通讯)可以创建丰富的多应用程序用户体验。定义进程间通讯的两个主要概念即:信道与消息。可以进程并向信道发送消息,任何时候只要到一个进程便可创建信道。
  • 扩展的字体格式:Qt 支持嵌入式 Linux 上的多种字体格式,包括:TrueType®, Postscript®Type1 与 Qt 预呈现字体。Qt 扩展了Unicode 支持,包括:构建时自动数据抽取和运行时自动更新。另外Qt还提供定制字体格式的插件,允许在运行时轻松添加新字体引擎。应用程序间的字体共享功能可以提高内存效率。

基本要求:

开发环境:Linux 内核 2.4 或更高;GCC 版本 3.3 或更高;用于 MIPS® GCC 版本 3.4. 或更高。
占用存储空间:存储空间取决于配置,压缩后: 1.7 – 4.1 MB,未压缩: 3.6 – 9.0 MB 。
硬件平台:易于载入任何支持带 C++ 编译器和帧缓冲器驱动Linux 的处理器。支持 ARM®,x86®, MIPS®, PowerPC® 。

2.Mac 平台

Qt 包括一套集成的开发工具,可加快在 Mac 平台上的开发。在编写 Qt 时,并不需要去设想底层处理器的数字表示法、字节序或架构。要在 Apple平台上支持 Intel 硬件,Qt 客户只需重新编辑其应用程序即可。

3.Windows平台

使用 Qt,只需一次性构建应用程序,无须重新编写源代码,便可跨多个 Windows操作系统的版本进行部署。Qt应用程序支持 WindowsVista、Server 2003、XP、NT4、Me/98 和 Windows CE。

4.Linux/X11平台

Qt 包括一套集成的开发工具,可加快在 X11 平台上的开发。Qt 由于是 KDE 桌面环境的基础,在各个 Linux 社区人尽皆知。几乎 KDE 中的所有功能都是基于 Qt 开发的, 而且 Qt 是全球社区成员用来开发 成千上万的开源 KDE 应用程序的基础。

5.Windows CE/Mobile

Qt 是用 C++ 开发的应用程序和用户界面框架。通过直观的 API,您可以使用 Qt 为大量的设备编写功能丰富的高性能应用程序。Qt 包括一套丰富的工具集与直观的API,意味着只须少数几行代码便可以更短的时间实现更高端的功能。

主要特点:

(1)硬件依存性极小;
(2)支持多数现有的 Windows CE 配置;
(3)对于自定义的硬件配置亦轻松构建;
(4)移植桌面代码至嵌入式平台,或通过重新编译,反之亦然;
(5)编译移除不常使用的组件与功能;
(6)利用系统资源并实现高性能;
(7)开发嵌入式设备尤如开发桌面系统一样轻松简单。

Qt 除了提供所有 工具 以及 API 与 类库 外,Qtfor Windows CE 还提供用于最优化嵌入式开发环境的附加功能。

本地化和可定制的外观:Qt 在使用时,可以支持 Windows Mobile 和 Windows CE 两种样式。 在运行时,Qt 应用程序将检测使用哪一种样式。 采用 Qt 样式表单,您只需要花费用于传统 UI 风格的少许时间和代码行,便可以轻松定制您的应用程序外观。特点:基于HTML 层叠式样式表 (CSS);适用于全部 widget;任何熟悉 CSS 技术的人员都可以定义复杂的样式。
先进的文本布局引擎:Qt for Windows CE 支持 TrueType® 和点阵字体。同时 Qt 还支持扩展的 Unicode 和从右至左的书写语言。Qt 的富文本引擎增加了新的功能用于复杂的文本布局,包括制表和路径追踪,以及环绕图形的文本。
基本要求:

开发环境: Microsoft® Visual Studio® 2005 (Standard Edition) 或更高ActivePerl 。
占用存储空间:紧凑配置 – 4.8 MB,全配置 – 8.4 MB。
操作系统:Windows CE 5 或更高,Windows Mobile 5 或更高。
硬件平台:支持 ARM®, x86®,(在 SH4® 和 MIPS® 上编译) 。

6.塞班平台(Symbian)

Qt 通过和S60 框架的集成为 Symbian平台提供了支持。在最新版的QtSDK 1.1中我们可以直接生成可以在塞班设备上运行的sis文件。

7.MeeGo平台 (Maemo 6 现更名为 MeeGo)

Qt 是一个功能全面的应用程序和用户界面框架,用来开发Maemo 应用程序,也可跨各主要设备和桌面操作系统部署这些程序且无需重新编写源代码的。 如果您在多数情况下开发适用于Symbian、Maemo 或 MeeGo 平台的应用程序,可以使用免费 LGPL 授权方式的 Qt。

Qt将为诺基亚设备运行MeeGo (Harmattan) 提供依托,并可为所有即将推出的 MeeGo 设备中的应用程序开发提供 API,为 Qt 开发人员提供了更多平台。不久,MeeGo 设备就会完全支持 (X11) Qt 。

Qt类库

模块化 Qt C++ 类库提供一套丰富的应用程序生成块(block),包含了生成高级跨平台应用程序所需的全部功能。

(1)先进的图形用户界面(GUI):Qt为您在桌面与嵌入式平台上开发先进的GUI应用程序,带来所有需要的功能。Qt使用所支持平台的本地化图形API,充分利用系统资源并给予应用程序本地化的界面。

  • 从按钮和对话框到树形视图与表格都具有完整的控件(窗体)
  • 自动缩放,字体、语言与屏幕定位识别布局引擎
  • 支持抗锯齿、矢量变形以及可缩放矢量图形 (SVG)
  • 具有样式API和窗体样式表,可完全自定义用户界面
  • 支持嵌入式设备的硬件加速图形和多重显示功能

(2)基于OpenGL ®与OpenGL ®Es的3D图形:OpenGL® 是一个标准的图形库,用于构建跨平台和支持硬件加速的高性能可视化应用程序。虽然OpenGL完美支持3D图形,但却不支持创建应用程序用户界面。Qt通过与OpenGL 的紧密集成解决了这一难题。

  • 在您的应用程序中轻松加入3D图形
  • 在嵌入式Linux 与Windows CE 平台上使用OpenGL ES和OpenGL绘画引擎
  • 利用系统资源实现最佳图形性能
  • 支持Windows 平台上的Direct3D®

(3)多线程:多线程编程是一个执行资源密集型操作而不会冻结应用程序用户界面的有效典范。Qt的跨平台多线程功能简化了并行编程,另外它附加的同步功能可以更加轻松地利用多核架构。

  • 管理线程、数据和对象更加轻松
  • 基于Qt的信号与槽,实现跨线程类型安全的对象间通讯
  • 高端API可以编译多线程程序而无须使用底端基元

(4)嵌入式设备的紧凑视窗系统:Qt构建在标准的 API基础上,用于具有轻量级window系统的嵌入式 Linux 设备。基于 Qt的应用程序直接写入 Linux 帧缓冲,解除了您对 X11 视窗系统的需求。

  • 减少内存消耗,内存占用更小
  • 可以编译移除不常使用的组件与功能
  • 可以利用硬件加速图形
  • 在桌面系统上的虚拟帧缓冲可用于嵌入式开发与调试

(5)对象间通讯:在开发用户图形界面中,一个常见的、重复发生系统崩溃与问题的症结根源是如何在不同组件之间进行通信。对于该问题,Qt 的解决方案是信号与槽机制,即执行Observer设计模式。我们可以简单理解为当特殊事件发生的时候,信号就被发出了,一个插槽就是一个函数,被称作特定信号的响应。

  • 信号与槽机制是类型安全的(type safe)
  • 任意信号都可以连接任意或多个插槽,或跨多个线程
  • 简化真正的组件编程

(6)2D图形:Qt给您提供一个功能强大的2D图形画布,用以管理和集成大量的图形元素。

  • 高精度可视化大量元素
  • 将窗体互动嵌入至图形场景中
  • 支持缩放、旋转、动画与变换

(7)多媒体框架:Qt使用

Phonon多媒体框架为众多的多媒体格式提供跨桌面与嵌入式操作系统的回放功能。Phonon可以轻松将音频与视频回放功能加入到Qt应用程序当中,并且在每个目标平台上提取多媒体格式与框架。

以平立的方式提供多媒体内容
从本地文件读取媒体或读取网络上的流媒体
提取Mac上的 QuickTime® ,Windows 上的DirectShow® 以及 Linux 上的Gstreamer

(8)WebKit集成:Qt WebKit集成,即Qt集成了WebKit功能,WebKit是KDE项目下基于 KHTML的开放源web浏览器引擎。目前 Apple®,Google™ 与Nokia等公司使用Qt WebKit集成。

将web与本地内容和服务整合在单一的富应用程序当中
快速创建整合实时web内容与服务的应用程序
使用集成在本地代码中的 HTML 与Java Script
完全控制跨平台的浏览器环境

(9)网络连接:Qt 让您网络编程更简单,并支持跨平台网络编程。

完整的客户/服务器插口提取
支持 HTTP,FTP,DNS 与异步 HTTP 1.1
无论HTML 和XML或图象与媒体文件,它都可以存取所有类型的数据

(10)XML:Qt 为XML 文件以及SAX 和 DOM 协议的C++实现,提供了一个流媒体文件读写器。同时 Qt 还包含了 XQuery – 一个简单的类似 SQL的查询语言,用于解析XML文件来选择和聚合所需要的XML元素,并且将它们转换成XML输出或其它格式的输出。

  • 仅需少数几行代码便可实现先进的 XML 查询
  • 完全支持 XQuery 1.0 和 XPath 2.0
  • 在您自己的应用程序中从XML查询、抽取和转换数据

(11)脚本引擎:Qt 包含一个完全集成 ECMA 标准的脚本引擎。 QtScript 提供 QObject 集成,把 Qt的信号与槽机制整合成脚本,并且实现了C++ 与脚本的集成。

基于ECMA 标准的脚本语言(ECMAScript 3是JavaScript1.5的基础)

  • 为简化的对象间通讯使用Qt的信号与槽机制
  • 开创新的契机将脚本与您的Qt应用程序相集成

(12)数据库:Qt 帮助您将数据库与您的Qt应用程序无缝集成。Qt支持所有主要的数据驱动,并可让您将SQL发送到数据库服务器,或者让 Qt SQL类自动生成 SQL 查询。

  • 支持所有主要的数据库驱动
  • 以多种视图或数据识别表单方式显示数据

Qt Quick介绍

Qt Quick是在Qt4.7中被引进的一项技术。Qt Quick 是一种高级用户界面技术,开发人员和设计人员可用它协同创建动画触摸式用户界面和应用程序。它由三部分构成:
(1)QML:像 JavaScript 一样的声明式语言;
(2)Qt Creator:在 Qt IDE中的直观工具;
(3)Qt Declarative:强大的 C++ 模块。

1.主要组成:

  • QML:基于 JavaScript 的直观语言 :QML 是一种简便易用的语言,开发人员与用户界面设计人员无需任何 C++ 知识,即可用其描绘出用户界面的外观和功能。
  • 面向开发人员和设计人员的共享工具:Qt Creator IDE2.1 版将集成一套开发人员与用户界面设计人员可共享,用以创建和实施 Qt Quick 项目的通用工具。
  • 通过 C++ 推动 QML 应用程序:在 Qt 库中的全新Declarative 模块支持生成动态可定制的用户界面,以及通过 C++ 拓展 QML 应用程序。

2.功能特点:

  • 快速开发动画式流畅多变的用户界面:通过直观的 QML 语言和一套丰富的 QMLElements——UI 和行为生成块——您可以快速创建出令人印象深刻的用户界面,比您想象的还要快。
  • 无需 C++ 知识:如果您具有 JavaScript 的经验或掌握基本的网络技术 (如 HTML 和 CSS),您就可以通过 QML 取得非常不错的成果。
  • 瞄准数以百万计的触摸屏设备:使用 Qt Quick,您可以为数以百万计的 Symbian 和 MeeGo 设备生成应用程序,或为各种类型的触摸屏消费类电子设备创建用户界面。

3.应用领域:

  • 汽车信息娱乐系统 UI:Cybercom Group 的用户界面设计人员与开发人员尝试使用 Qt Quick 为其汽车信息娱乐平台设计 UI——并取得了令人满意的结果。
  • 社交媒体电视:mixd.tv 使用 Qt Quick 为其跨平台网络电视应用程序创建 UI,其用户可以通过社交媒体频道访问和共享在线视频的内容。
  • 联网汽车:Qt 的认证合作伙伴 Digia 很快学会了 Qt Quick 并用其创建出了包括导航、电话、游戏和音乐功能的高级汽车 UI。

Qt授权

Qt Commercial Developer License

The Qt Commercial Developer License is the correctlicense to use for the development of proprietary and/or commercial softwarewith Qt where you do not want to share any source code.

You must purchase a Qt Commercial DeveloperLicense from us or from one of our authorized resellers before you startdeveloping commercial software as you are not permitted to begin yourdevelopment with an open source licensed Qt version and convert to thecommercially license version at a later . The Qt Commercial Developer Licenseincludes a restriction that prevents the combining of code developed with theQt GNU LGPL v. 2.1 or GNU GPL v. 3.0 license versi with commerciallylicensed Qt code.

Qt GNU LGPL v. 2.1 Version

This version is available for development ofproprietary and commercial applicati in accordance with the terms andconditi of the GNU Lesser General Public License version 2.1.

Support services are available separately forpurchase.

Qt GNU GPL v. 3.0 Version

This version is freely available for the developmentof open source software governed by the GNU General Public Licenseversion 3.0 (“GPL”).

Support services are available separately forpurchase.

License Comparison Chart

CommercialLGPLGPL
License costLicense fee chargedNo license feeNo license fee
Must provide source code changes to QtNo, modificati can be closedSource code must be providedSource code must be provided
Can create proprietary applicatiYes – No source code must be disclosedYes, in accordance with the LGPL v. 2.1 termsNo, applicati are subject to the GPL and source code must be made available
Updates providedYes, immediate notice sent to those with a valid support and update agreementYes, made availableYes, made available
SupportYes, to those with a valid support and update agreementNot included but available separately for purchaseNot included but available separately for purchase
Charge for RuntimesYes, for some embedded usesNoNo

Qt5简介

Qt 5是进行Qt C++软件开发基本框架的最新版本,其中Qt Quick技术处于核心位置 。同时Qt 5能继续提供给开发人员使用原生QtC++实现精妙的用户体验和让应用程序使用OpenGl/OpenGL ES图形加速的全部功能。通过Qt 5.0提供的用户接口,开发人员能够更快的完成开发任务,针对触摸屏和平板电脑的UI转变与移植需求,也变得更加容易实现.

2012年12月19日,Digia宣布正式发行Qt 5.0。Qt 5.0是一个全新的流行于跨平台应用程序和用户界面开发框架的版本,可应用于桌面、嵌入式和移动应用程序。Qt 5 在性能、功能和易用性方面做了极大的提升,并将于明年可完全支持 Android 和 iOS 平台。Digia明确表明要使Qt 成为世界领先的跨平台开发框架。Qt 5在这个过程中具有重要的意义,它为应用程序开发人员和产品用户提供了最好的用户体验。Qt 5极大地简化了开发过程,让他们能够更快地为多个目标系统开发具有直观用户界面的程序。它还可以很平滑的过度到新的开发模式来满足触摸屏和 Tablet 的需求。

Qt 5的主要优势包括:
图形质量;中低端硬件上的高性能;跨平台移植性;支持 C + + 11; QtWebKit 2 支持的 HTML5;大幅改进QML引擎并加入新的 API;易用性并与 Qt 4 版本兼容。

  • 出色的图像处理与表现能力:Qt Quick 2 提供了基于GL的工作模式,它包括一个粒子系统和一系列着色效果集合。Qt Quick 2 让复杂图形的细腻动画和变形处理变得更加容易,也确保了低端架构中2D和3D效果的平滑渲染效果和在高端架构中一样的出色。
  • 更高效和灵活的研发: JavaScript和QML在保证对C++基础和Qt Widget支持上发挥着重要作用。Qt Webkit 2中一部分功能就在使用或者正考虑通过HTML 5,彻底的改变Qt
  • 跨平台的移植变得更加简单:对于OS开发人员来说,由于基础模块和插件模块采用了新的架构,以及Qt跨平台性的继续强化,Qt已经能够运行在所有的环境中了。而我们的下一步计划:全面的支持iOS和Android系统,现在正在如火如荼的开发中。

Qt 通过使用 OpenGL ES,大大的增加了交付令人印象深刻的图形的能力 (OpenGL ES 是一个专门为嵌入式系统和移动设备而制定的图形应用程序编程接口)。这使它更容易开发和部署具有绚丽动画效果的 2D、3D 图形应用,这些应用在各种性能级别的嵌入式设备上得到平滑运行。例如手机、平板电脑和低成本的开发平台包括 Raspberry Pi。Qt5 新的模块化的代码库使得 Qt5 的跨平台移植性变得更简单。它包含了要点模块组和附加模块组,这种设计会减小系统代码库的尺寸。整合的 Qt 平台抽象层还强调跨平台移植性,开发人员可以通过启用开发简便性为多个目标部署。Qt 支持所有主要的桌面操作系统,包括 Windows,Mac OS X 和 Linux。嵌入式操作系统包括嵌入式 Linux、Windows 嵌入式以及最广泛部署实时操作系统的嵌入式设备——VxWorks、Neutrino 和 INTEGRITY和流行的移动操作系统等等。Qt WebKit 2 集成浏览器引擎,允许轻松集成 web 内容和应用程序。它将使 HTML5 开发人员感觉轻松自如,基于 Qt WebKit 2,能够开发出兼顾响应能力和本地代码强大功能的混合应用。这些应用可以提供大量的动态内容。

只需要一个简单的重新编译,就可以直接迁移之前为 Qt4 开发的应用程序。

Qt6的技术概览

  • Qt对用户的价值体现在哪里?

Qt已经成功应用与许多不同的行业,并且在不断的横向发展,Qt对用户的核心价值体现如下:
(1)跨平台特性,用户可使用一种技术,把一套代码部署到各种的桌面、移动和嵌入式平台
(2)可扩展性,覆盖了从低端的单用途设备到高端复杂的桌面应用程序和互联系统
(3)世界一流的API、工具和文档,简化了应用程序和设备的开发流程
(4)可维护性、稳定性和兼容性,轻松维护大型代码库
(5)拥有超过100万用户的大型开发者生态
新版本的Qt需要我们进行一些调整以适应新的市场需求,同时也要把上述5个价值观作为我们工作的核心内容。 桌面应用是Qt的基础,也是Qt得以成长和强大的市场,桌面应用是我们大多数用户第一次接触Qt的地方,也是组成Qt工具链的基础。保持桌面应用的健康和成长是在其他市场也保持增长的先决条件。 嵌入式和互联设备是我们增长最快的领域。触屏设备的数量正在以指数级增长,但这些设备的硬件价格却承受着巨大压力。低端芯片组,单片机,结合中小型触摸屏的设备将无处不在。这些设备中的大多数都是功能相对简单的,但它们都需要精致流畅的用户界面。因此我们需要确保我们的产品能够瞄准这个空间,从而实现我们的可扩展的承诺。 与此同时,高端设备的用户界面的复杂性将继续增加,它们往往包括了数千个不同的屏幕和许多的应用程序。将2D和3D元素合并到一个用户界面也是很常见的,增强和虚拟现实的使用也是如此。 人工智能的元素将更广泛地应用于应用程序和设备中,我们需要有简单的方法来集成这些元素。 正在创建的互联设备数量的强劲增长,以及对用户体验的更高要求,使得我们更有必要专注于开发全球领先的工具,以简化应用程序和设备的创建流程。将UX设计人员集成到开发工作流中是我们的目标之一,但是我们还需要在许多其他领域去尝试进一步简化用户的工作。 Qt 6将是Qt的一个新的重大版本,这个版本的主要目标是为2020年以后的需求做好准备,在此次过程中我们将对代码库进行整理,使其更容易维护。重点将放在Qt中那些需要调整软件架构的部分,但是如果不破坏与Qt 5.x兼容性,那这部分就无法完成。 为了适应未来几年的需求,下面是我们会对Qt进行的的一些关键性修改。

  • 新一代的QML

QML和Qt Quick是过去几年推动Qt增长的主要技术。使用这些技术可以直观的创建用户界面是我们产品的一个独特卖点。 QML是为Qt 5创建的,但是它有一些问题和限制。这也意味着它可以大幅改进,我们计划在Qt 6中实现这些改进。我们计划如下: 引入强类型。弱类型使得用户很难对他们的代码库进行大的更改。一个强大的类型系统允许IDE和其他工具帮助用户完成这项任务,并极大地简化了维护成本。此外,它还有助于我们生成性能更好的代码和减少相关开销。 JavaScript成为QML的一个可选特性。使用QML时使用完整的JavaScript引擎会提升复杂性,而且会引起性能上的开销,尤其是在单片机等低端硬件上,性能开销更加明显。然而,这个特性在许多其他应用场景中非常有用。 去掉了QML的版本控制。通过简化QML中的某些查找规则并更改上下文属性的工作方式,我们可以消除QML中的版本控制。反过来,这将大大的简化QML引擎,极大地简化我们维护Qt Quick的工作负担,并为用户简化QML和Qt Quick的使用流程。 删除QObject和QML之间重复的数据结构 目前我们的元对象系统和QML之间有相当多重复的数据结构,这些重复的数据结构会降低启动性能,增加内存使用量。通过统一这些数据结构,我们能够减少许多开销。 避免运行时生成数据结构。这与上面的一点有关,其中许多重复的数据结构目前都是在运行时生成的。其中大多数完全有可能在编译时生成。 支持把QML编译成高效原生的C++代码。通过强大的类型和更简单的查找规则,我们可以将QML转换为高效原生的C++代码,从而显著提高运行时性能 支持隐藏实现细节。为了能够在QML组件中隐藏数据和功能,对方法和属性进行“私有化”一直是一个长期的需求。 更好的工具集成。我们当前的QML代码模型时常不完整,这使得重构和在编译时检测错误变得困难甚至不可能。通过上述更改,应该能够提供与C++相媲美的编译时诊断以及大幅改进的重构支持。

  • 下一代图形

自从Qt 5.0以来,图形领域发生了很多变化,这导致我们不得不对图形栈进行重大更改,以保持其竞争力。 在Qt 5中,我们统一使用OpenGL作为3D图形的API。从那时起,产生了许多新的API。在Linux上Vulkan是OpenGL的指定接班人,苹果正在推动Metal的发展,而微软有Direct 3D。这意味着Qt将来必须与所有这些API无缝地衔接。为了实现这一点,必须定义一个新的图形抽象层的API(类似于平台集成层的QPA),称为渲染硬件接口(RHI)。我们需要将所有的渲染基础设施(QPainter、Qt Quick Scenegraph和我们的3D支持)建立在该层的基础之上。 不同图形API的合成也导致我们必须支持不同的着色语言。Qt着色器工具模块将帮助我们在编译和运行时交叉编译着色器。 3D正在扮演越来越重要的角色,而我们目前的产品还没有一个统一的解决方案来创建同时包含2D和3D元素的UI。目前,将QML与Qt 3D或3D Studio中的内容集成是很麻烦的,并且会导致一些性能开销。此外,在2D和3D内容之间进行逐帧的动画同步和转换还没有办法做到。 3D内容与Qt Quick新的集成方式就是为了解决这个问题。在这种情况下,一个全新的渲染器将允许同时渲染2D和3D内容,并支持两者之间的任意嵌套。这将把QML转换为3D UI的UI定义语言,并且不再需要UIP格式。我们将提供一个新的技术预览版本的Qt Quick与3D支持的版本,它已经包含在了Qt 5.14中,更多的信息将会在一个单独的博文中进行说明。 最后,新的图形栈需要强大的图形素材处理的支持,它能在编译时根据目标硬件预处理这些素材并在需要时使用。比如将PNG文件转换为压缩纹理格式,将许多文件编译为纹理图集,将着色器和网格转换为优化的二进制格式等等。 我们还打算为Qt 6引入统一的主题样式引擎,这将允许我们在桌面和移动平台上获得Qt Widgets和Qt Quick的原生外观。

  • 统一并且一致的工具库

我们创建用户界面的图形工具已经被一分为二,包括Qt 3D Studio和Qt Design Studio。此外,Qt 3D Studio与Qt的其余部分有些脱节,导致了相当多的重复工作。 我们通过将Qt 3D Studio所需的功能合并回Design Studio来统一这些功能。Design Studio与Qt Creator共享了大量代码和应用/插件框架,提供了很好的设计体验,并为我们提供了在设计师和开发者之间搭建桥梁的工具。 设计工具还需要与Photoshop、Sketch、Illustrator、Maya、3D Max等内容创建工具进行良好的集成。 开发者工具需要大量的投入,这样我们才能提供对C++、QML和Python等提供最佳的支持。提供统一工具还意味着开发人员可以很容易地使用Qt Creator中的设计功能,而UX设计者可以从开发者工具的特性(如编译项目或在设备上测试)中获益。 QMake作为Qt 5中使用的构建系统有很多缺陷和限制。对于Qt 6,我们的目标是使用CMake作为标准的第三方构建系统来构建Qt。到目前为止,CMake是C++世界中使用最广泛的构建系统,我们迫切需要更好地与它集成。在QMake上我们将继续支持用户,但不会对其进一步开发或用来构建Qt框架本身。

  • 增强已有的C++ API

C++在过去的几年中发生了很大的变化。虽然Qt 5.0必须以C++ 98为基础,但现在Qt 6可以依赖C++ 17。这意味着C++提供了更多的开箱即用的功能,这在我们使用Qt 5时是没有的。我们使用Qt 6的目标是更好地集成这些能力,同时也保持向前的兼容性。 Qt 6中,我们希望把QML和Qt Quick的一些功能引入到C++中。我们致力于为QObject及其相关类引入一个新的属性系统,将QML中的绑定引擎集成到Qt的核心中,并使其在C++中可用。新的属性系统和绑定引擎将显著降低绑定的运行时开销和内存消耗,并使它们可用于Qt的所有部分,而不仅仅是Qt Quick。

  • 语言支持

在Qt 5.12中,我们引入了对Python的支持,并通过Qt为WebAssembly添加了浏览器作为新的平台。在发布6.0之后,保持并进一步扩展跨平台特性将是Qt 6系列的一个重要部分。

  • 兼容Qt 5和增量改进

与旧版本的兼容性是非常重要的,也是我们开发Qt 6时的主要需求。用户已经使用我们的框架编写了数十亿行代码,因此,我们所做的任何不兼容的更改都会给用户带来额外的成本。此外,对Qt 6的更改要求用户做的工作越多,用户升级的速度就会越慢,这将导致维护Qt 5的最后一个版本的成本更高。 因此,在用户代码中我们应该避免触发编译时或运行时错误进而使得Qt运行崩溃。如果我们必须破坏兼容性,编译时错误比运行时的静默破坏更可取(因为后者更难检测)。 当我们确实需要删除Qt的某些废弃部分,那么我们必须要确保它不会影响用户需要的部分,大部分用户都在使用的关键功能,比如Qt Widgets和其他部分毫无疑问必须保留。 我们正在计划对核心类和功能进行许多在Qt 5中无法实施的增量改进。我们的目标是保持完整的源代码兼容性,但是由于我们可以打破Qt 6的二进制兼容性,我们可以做很多在Qt 5中无法完成的清理和改进。 除了这些,我们还将对Qt 6进行其它的清理。我们将删除Qt 5中已经废弃的大部分功能(函数、类或模块)。从长远来看,这种清理将有助于节省开发人员的时间,并允许我们把更多的精力放在维护和编码上。 然而,对弃用部分的移植需要尽可能的简单,我们的用户可以完美地使用Qt 5.15 LTS增量地完成这一工作。我们的目标应该是Qt 6与Qt 5.15 LTS足够兼容,这样就可以轻松地维护一个可以同时针对两个版本编译的大型代码库。

  • 市场和技术产品结构

除了改进Qt框架和工具,我们的目标是为组件和开发工具创建一个新的市场。这个方向将面向开发、设计应用程序和嵌入式设备的直接使用者,而不是面向最终用户。因此,它将成为Qt生态系统的一个凝聚中心。它将为第三方厂商提供一个发布Qt扩展组件的场所,扩展可以是免费或商业的。 Qt在过去的几年里增长良多,当前最重要的任务就是发布一个新版本。在Qt 6中,我们有机会重组我们的产品,并将必要的框架和工具打包为一个更小的核心。我们将利用应用市场来交付我们的附加框架和工具,而不是作为与核心Qt产品紧密耦合的捆绑包。这将使我们在何时交付以及如何交付方面具有额外的灵活性,并允许我们为某些附加组件解耦发布计划。

任务要求:自学P188的有关显示显存、显示字符串的学习材料,在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串“welcome  to masm”。

一、分析设计想法

这个题目的本质是循环读取字符,将字符复制到寄存器中并放到指定的显存内存单元中,并控制好字符的属性字节即可,非常有趣,能比较直观的控制显存。

二、程序的设计

 

 

assume cs:codesg

data segment

  db 'welcome to masm!'

data ends

 

 stack segment

  

 stack ends

 

codesg segment

 

start:

     mov ax,data

        mov ds,ax

        mov ax,0B800H

        mov es,ax;将显存的位置放入es

        

        mov cx,16

        mov si,0

        mov di,12*160+64 ;屏幕中央

s0:

     mov al,ds:[si]

        mov ah,00000010B   ;黑底绿色

        mov es:[di],ax ;将数据段的字符放入附加段(即显存中)

        inc si

        add di,2

        loop s0

        

        add di,160-32   ;下一行

        mov si,0

        mov cx,16

        

s1:

     mov al,ds:[si]

        mov ah,00100100B    ;绿底红字

        mov es:[di],ax;将数据段的字符放入附加段(即显存中)

        inc si

        add di,2

        loop s1

        

        add di,160-32   ;下一行

        mov si,0

        mov cx,16

        

s2:

     mov al,ds:[si]

        mov ah,01110001B    ;白底蓝色

        mov es:[di],ax; 将数据段的字符放入附加段(即显存中)

        inc si

        add di,2

        loop s2

        

        mov ax,4c00H

        int 21H

         

  codesg ends

  end start

 

三、程序的结果

四、心得体会

通过自学汇编程序设计有关显示显存、显示字符串的学习材料,我了解了显存在内存地址空间中的位置是B8000H~BFFFFH共32KB的空间,并且知道了如何将字符输出到屏幕中央,举一反三,我可以随心所欲的将我想要输出的内容输出到屏幕上的任何一个地方,并能控制字符颜色,字符背景颜色以及字符是否闪烁和是否高亮,学习了许多新的知识,开扩了自己的眼界。

任务说明:某公司从1975成立一直到1995年的基本情况如下:

年份 收入(千美元) 雇员(人) 人均收入(千美元)
1975 16 3 ?
1976 22 7 ?
1977 382 9 ?
1978 1356 13 ?
1979 2390 28 ?
8000 38 ?
1995 5937000 17800 ?

已知程序中的数据按下面的方式定义:

 

assume cs:codesg,ds:datasg,es:table

datasg segment

 db '1975','1976','1977','1978','1979','1980','1981','1982','1983'

db '1984','1985','1986','1987','1988','1989','1990','1991','1992'

db '1993','1994','1995'

       ;以上是表示21年的21个字符串

 dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

 dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000

dd 5937000

           ;以上是公司21年总收入

dw 3,7,9,13,28,38,130,220,476,78,1001,1442,2258,2793,4037,5635,8226

dw 11542,14430,15257,17800

以上表示21年每年雇佣人数

dataend

table segment

           db 21 dup ('year summ ne ?? ')

table ends

 

编程,将data段中的数据按如下格式写入到table段中,并计算21年中的人均收入(取整),结果也按照下面的格式保存在table段中

年份(4字节) 空格 收入(4字节) 空格 雇员数

(2字节)

空格 人均收入(2字节) 空格
行内

地址

1年

1行

每行的始址

0 1 2 3 4 5 6 7 8 9 A B C D E F
Table:0H ‘1975’ 16 3 ?
Table:10H ‘1976’ 22 7 ?
Table:20H ‘1977’ 382 9 ?
Table:30H ‘1978’ 1356 13 ?
Table:40H ‘1979’ 2390 28 ?
…. 8000 38 ?
Table:140H ‘1995’ 5937000 17800 ?

 

一、分析设计想法

这个题目的本质是循环读取字符串,将字符串复制到寄存器中并放到指定的内存单元中,同时用到了除法,只要一步一步稳扎稳打的进行,一般是不会出现错误的。

 

二、程序的设计

 

assume cs:codesg

data segment

  db '1975','1976','1977','1978','1979','1980','1981','1982','1983'

  db '1984','1985','1986','1987','1988','1989','1990','1991','1992'

  db '1993','1994','1995'

  dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

  dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

  dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226

  dw 11542,14430,15257,17800

 

  data ends

 

 table segment

    db 21 dup ('year summ ne ?? ');首先覆盖掉空的内存单元,方便查看结果

 table ends

 

 stack segment

   dw 0,0,0,0,0,0,0,0;定义堆栈段

 stack ends

 

codesg segment

 

start:

          mov ax,table

          mov es,ax

          mov ax,data

          mov ds,ax

         

          mov bx,0 ;存年份偏移

          mov si,0 ;存人数偏移

          mov di,0 ;存table段中偏移

         

          mov cx,21 ;循环21年

 

       s0:

          ;将数据段中的年份复制到附加段中

          mov ax,[bx]

          mov es:[di],ax

          mov ax,[bx+2]

          mov es:[di+2],ax

         

          ;将数据段中的收入复制到附加段中

          mov ax,[bx+84]

          mov es:[di+5],ax

          mov ax,[bx+86]

          mov es:[di+7],ax

 

       ;将数据段中的人数复制到附加段中

       mov ax,[si+168]

       mov es:[di+10],ax

         

          ;通过除法计算出人均收入

          mov ax,[bx+84];低位

          mov dx,[bx+86];高位

          div word ptr [si+168];商存在ax中

          mov es:[di+13],ax

         

       add bx,4

          add si,2

          add di,16

     loop s0

        

 

  mov ax,4c00H

  int 21H

 
  codesg ends

  end start

 

三、程序的结果

四、心得体会

通过这个大作业程序的设计,我进一步掌握了堆栈段,数据段和附加段的简单使用,并且学会了如何在汇编语言中使用除法,在除法的过程中分别用哪些存储器存储数据,并通过格式化的控制,能够存储较为整齐的数据,在学习汇编语言程序设计的过程中,我常常会遇到自己没有思绪的程序,完全不知道该怎么写,或者按照我思考的样子却写不出我想要的结果,但是慢慢修改,慢慢积累,遇到的坑多了,也就不容易遇到坑了,写不好没关系,哪怕再小的程序,多写多改,慢慢地我就会提高的。

(1)进程与线程的区别?

调度:线程是独立调度的基本单位,进程是拥有资源的基本单位。在同一进程中,线程的切换不会引起进程的切换;在不同的进程中,进行线程切换,则会引起进程的切换。
拥有资源:进程是拥有资源的基本单位,线程不拥有资源,但线程可以共享器隶属进程的系统资源。
并发性:进程可以并发执行,而且同一进程内的多个线程也可以并发执行,大大提高了系统的吞吐量。
系统开销:创建和撤销进程时,系统都要为之分配或回收资源,在进程切换时,涉及当前执行进程CPU环境的保存以及新调度的进程CPU环境的设置;而线程切换时只需保存和设置少量寄存器内容,因此开销很小,另外,由于同一进程内的多个线程共享进程的地址空间,因此这些线程之间的同步与通信比较容易实现,甚至无须操作系统的干预。
通信方面:进程间通信需要借助操作系统,而线程间可以直接读/写进程数据段来进行通信。

(2)进程间的通信方式?

  • 管道( pipe )
  • 有名管道 (named pipe)
  • 信号量( semophore )
  • 消息队列( message queue )
  • 信号 ( signal )
  • 套接字( socket )
  • 共享内存(Shared Memory)

(3)线程间的通信方式?

  • 事件(Event);
  • 信号量(semaphore);
  • 互斥量(mutex);
  • 临界区(Critical section)

(4)栈和堆的区别?

1、在申请方式上

(stack): 现在很多人都称之为堆栈,这个时候实际上还是指的栈。它由编译器自动管理,无需我们手工控制。 例如,声明函数中的一个局部变量 int b 系统自动在栈中为b开辟空间;在调用一个函数时,系统自动的给函数的形参变量在栈中开辟空间。

(heap): 申请和释放由程序员控制,并指明大小。容易产生memory leak。

在C中使用malloc函数。

如:char *p1 = (char *)malloc(10);

在C++中用new运算符。

如:char *p2 = new char(20);

但是注意p1本身在全局区,而p2本身是在栈中的,只是它们指向的空间是在堆中。

2、申请后系统的响应上

(stack):只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

(heap): 首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete或 free语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

3、申请大小的限制

(stack):在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow。因此,能从栈获得的空间较小。例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。

注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。

(heap): 堆是向高地址扩展的数据结构,是不连续的内存区域(空闲部分用链表串联起来)。正是由于系统是用链表来存储空闲内存,自然是不连续的,而链表的遍历方向是由低地址向高地址。一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。由此可见,堆获得的空间比较灵活,也比较大。

4、分配空间的效率上

(stack):栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。但程序员无法对其进行控制。

(heap):是C/C++函数库提供的,由new或malloc分配的内存,一般速度比较慢,而且容易产生内存碎片。它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。这样可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。显然,堆的效率比栈要低得多。

5、堆和栈中的存储内容

(stack):在函数调用时,第一个进栈的是主函数中子函数调用后的下一条指令(子函数调用语句的下一条可执行语句)的地址,然后是子函数的各个形参。在大多数的C编译器中,参数是由右往左入栈的,然后是子函数中的局部变量。

注意:静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中子函数调用完成的下一条指令,程序由该点继续运行。

(heap):一般是在堆的头部用一个字节存放堆的大小,堆中的具体内容有程序员安排。

堆和栈的区别可以用如下的比喻来看出: 使用栈就象我们去饭馆里吃饭,只管点菜(声明变量)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

(5)C++和C的区别?

C是一个结构化语言,它的重点在于算法和数据结构。对于语言本身而言,C是C++的子集。C程序的设计首要考虑的是如何通过一个过程,对输入进行运算处理,得到输出。对于C++,首要考虑的是如何构造一个对象模型,让这个模型能够配合对应的问题,这样就可以通过获取对象的状态信息得到输出或实现过程控制。

因此,C与C++的最大区别在于,它们用于解决问题的思想方法不一样。

C实现了C++中过程化控制及其他相关功能。而在C++中的C,相对于原来的C还有所加强,引入了重载、内联函数、异常处理等。C++更是拓展了面向对象设计的内容,如类、继承、虚函数、模板和包容器类等。

在C++中,不仅需要考虑数据封装,还需要考虑对象的粒度的选择、对象接口的设计和继承、组合与继承的使用等问题。

相对于C,C++包含了更丰富的设计概念。

(6)BST,AVL树,红黑树的区别?

二叉查找树(BST)

二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质,是指一棵空树具有如下性质:

  • 任意节点左子树不为空,则左子树的值均小于根节点的值.
  • 任意节点右子树不为空,则右子树的值均大于于根节点的值.
  • 任意节点的左右子树也分别是二叉查找树.
  • 没有键值相等的节点.

AVL树

AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,和红黑树相比,它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1).不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入删除次数比较少,但查找多的情况。

红黑树

一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是red或black. 通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍.它是一种弱平衡二叉树(由于是弱平衡,可以推出,相同的节点情况下,AVL树的高度低于红黑树),相对于要求严格的AVL树来说,它的旋转次数变少,所以对于搜索,插入,删除操作多的情况下,我们就用红黑树.

性质

  • 每个节点非红即黑.
  • 根节点是黑的。
  • 每个叶节点(叶节点即树尾端NUL指针或NULL节点)都是黑的.
  • 如果一个节点是红的,那么它的两儿子都是黑的.
  • 对于任意节点而言,其到叶子点树NIL指针的每条路径都包含相同数目的黑节点.
  • 查找、插入和删除的时间复杂度都是O(logn)

(7)产生死锁的必要条件?已经如何预防死锁?

一、计算机系统中的死锁

竞争不可抢占性资源引起死锁
竞争可消耗资源引起死锁
进程推进顺序不当引起死锁
二、产生死锁的必要条件

互斥条件(资源独占)
请求和保持条件
不可抢占条件(不可剥夺)
循环等待条件
三、处理死锁的方法

预防死锁
避免死锁
检测死锁
解除死锁
四、预防死锁

破坏‘请求和保持’条件
破坏‘不可抢占条件’条件
破坏‘循环等待’条件
(主要是破坏产生死锁的后三个条件)

五、解决死锁

最简单的办法是终止各锁住进程,或按一定的顺序中止进程序列,直到已释放到有足够的资源来完成剩下的进程时为止。
也可以从被锁住进程强迫剥夺资源以解除死锁

(8)TCP和UDP的区别?

TCP和UDP的区别:

传输控制协议TCP的特点:

(1) TCP是面向连接的运输层协议

(2) 每一条TCP连接只能有两个端口,即:点对点

(3) TCP提供可靠交付的服务

(4) TCP提供全双工通信

(5) 面向字节流,TCP中的“流”指流入到进程或从进程流出的字节序列

用户数据报协议UDP的特点:

(1) UDP是无连接的

(2) UDP使用尽最大努力交付

(3) UDP是面向报文

(4) UDP没有拥塞控制

(5) UDP支持一对一、一对多、多对一和多对的的交互通信

(6) UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短

(9)TCP状态中 time_wait 的作用?

TCP状态中 time_wait 的作用:

客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间。这么做有两个理由:

确保最后一个确认报文段能够到达。如果 B 没收到 A 发送来的确认报文段,那么就会重新发送连接释放请求报文段,A 等待一段时间就是为了处理这种情况的发生。
可能存在“已失效的连接请求报文段”,为了防止这种报文段出现在本次连接之外,需要等待一段时间。

(10)HTTP 2.0与HTTP 1.0的区别 ?

  1. HTTP/2采用二进制格式而非文本格式
  2. HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
  3. 使用报头压缩,HTTP/2降低了开销
  4. HTTP/2让服务器可以将响应主动“推送”到客户端缓存中

(11)HTTP与HTTPS的区别?

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca(证书授权机构:Certificate Authority )申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

(12)TCP的三次握手和四次挥手的过程?

在这里插入图片描述

在这里插入图片描述

(13)事务具有四个特性?

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持续性(Durability)

(14)树的先序、中序和后序的递归和非递归实现?

树的先序递归:

void PreOrder(Tree* root)
{
	if (root != nullptr)
	{
		cout << root->date << " ";
		PreOrder(root->lchild);
		PreOrder(root->rchild);
	}
}

树的先序非递归:

void PreOrder(Tree* root)
{
	stack<Tree* > Stack;
	if (root == nullptr)
		return;
	while (root != nullptr || !Stack.empty())
	{
		while (root != nullptr)
		{
			Stack.push(root);
			cout << root->date << " ";
			root = root->lchild;
		}
		root = Stack.top();
		Stack.pop();
		root = root->rchild;
	}
}

树的中序递归:

void InOrder(Tree* root)
{
	if (root != nullptr)
	{
		InOrder(root->lchild);
		cout << root->date << " ";
		InOrder(root->rchild);
	}
}

树的中序非递归:

void InOrder(Tree* root)
{
	stack<Tree*> s;
	while (root != nullptr || !s.empty())
	{
		if (root != nullptr)
		{
			s.push(root);
			root = root->lchild;
		}
		else
		{
			root = s.top();s.pop();
			cout << root->date << " ";
			root = root->rchild;
		}
	}
}

树的后序递归:

void PostOrder(Tree* root)
{
	if (root != nullptr)
	{
		PostOrder(root->lchild);
		PostOrder(root->rchild);
		cout << root->date << " ";
	}
}

树的后序非递归:

void PostOrder(Tree* root)
{
	stack<Tree*> s;
	Tree* r = nullptr;//使用辅助指针,指向最近访问过的节点
	while (root != nullptr || !s.empty())
	{
		if (root != nullptr)
		{
			s.push(root);
			root = root->lchild;
		}
		else
		{
			root = s.top();
			if (root->rchild != nullptr && root->rchild != r)
				root = root->rchild;
			else
			{
				s.pop();
				cout << root->date << " ";
				r = root;
				root = nullptr;
			}
		}
	}
}

(15)树的层次遍历?

void LevelOrder(Tree* root)
{
	if (root == nullptr)
		return;
	queue<Tree*> que;
	que.push(root);
	while (!que.empty())
	{
		root = que.front();
		cout << root->date << " ";
		que.pop();
		if (root->lchild != nullptr)
			que.push(root->lchild);
		if (root->rchild != nullptr)
			que.push(root->rchild);
	}
}

(16)static关键字的作用?

static关键字的作用:

(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;

(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

(17)const关键字的作用?

const关键字的作用:

(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;

(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;

(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;

(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的 成员变量;

(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。

(18)指针和引用的区别?

  1. 指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;引用的底层是const指针,引用同样占据一块内存。
  2. 引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化。

(19)哈希表处理冲突的方法?

(1) 链地址法

链地址法是指把所有的冲突关键字存储在一个线性链表中,这个链表由其散列地址唯一标识。

(2) 开放定址法

开放定址法是指可存放新表项的空闲地址,既向它的同义词表项开放,又向它的非同义词表项开放。其数学递推公式为(Hi表示冲突发生后第i次探测的散列地址)

Hi = (H(key) + di) % m

式中,i = 1,2,…,k,m为散列表表长,di为增量序列。di通常有以下几种取法:

当di = 1,2,…,m – 1时,称为线性探测法。其特点是,冲突发生时顺序查看表中下一个单元,直到找出一个空单元或查遍全表。

当di = 12,-12,22,-22,…,k2,-k2时,又称为二次探测法。

当di = 伪随机数序列时,称为伪随机探测法。

(3) 再散列法

当发生冲突时,利用另一个哈希函数再次计算一个地址。直到冲突不再发生。

(4) 建立一个公共溢出区

一旦由哈希函数得到的地址冲突,就都填入溢出表。

(20)面向对象的三大特性?

继承、封装、多态

(21)多态的实现?

(1)编译时的多态性。编译时的多态性是通过重载来实现的。对于非虚的成员来说。系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。

(2)运行时的多态性。运行时的多态性就是直到系统运行时,才根据实际情况决定实现何种操作。C++中,运行时的多态性通过虚函数实现。

(22)深拷贝和浅拷贝的区别?

浅拷贝

对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数,调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,但是程序结束时该内存却被释放了两次,会造成内存泄漏问题。

深拷贝

在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生,调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。

总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

(23)vector的实现原理

vector的数据安排以及操作方式,与array非常相似。两者的唯一区别在于空间的运用的灵活性。array是静态空间,一旦配置了就不能改变;要换个大(或小)一点的房子,可以,一切琐细都得由客户端自己来:首先配置一块新空间,然后将元素从旧址一一搬往新址,再把原来的空间释还给系统。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不必因为害怕空间不足而一开始要求一个大块头的array了,我们可以安心使用array,吃多少用多少。

vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率。一旦vector的旧有空间满载,如果客户端每新增一个元素,vector的内部只是扩充一个元素的空间,实为不智。因为所谓扩充空间(不论多大),一如稍早所说,是” 配置新空间/数据移动/释还旧空间 “的大工程,时间成本很高,应该加入某种未雨绸缪的考虑。稍后我们便可看到SGI vector的空间配置策略了。

另外,由于 vector维护的是一个连续线性空间,所以vector支持随机存取 。

注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此, 对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 。这是程序员易犯的一个错误,务需小心。

(24)C++ 源代码到可执行代码的详细过程 ?

https://maplefan.com/index.php/2018/12/06/编译预处理/

(25)memcpy和strcpy的区别 ?

memcpy和strcpy的区别?

strcpy和memcpy主要有以下3方面的区别。

复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符”\0″才结束,如果空间不够,就会引起内存溢出。memcpy则是根据其第3个参数决定复制的长度。
用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy,由于字符串是以“\0”结尾的,所以对于在数据中包含“\0”的数据只能用memcpy。
从s1复制字符串到s2

strncpy和memcpy很相似,只不过它在一个终止的空字符处停止。当n>strlen(s1)时,给s2不够数的空间里填充“\0”(n为s2的空间大小);当n<=strlen(s1)时,s2是没有结束符“\0”的,所以使用strncpy时,确保s2的最后一个字符是“\0”。

(26)vector删除数据时有什么需要注意的吗 ?

先用迭代器指向vector的起始位置,然后用while循环,找到符合的元素,删除迭代器所指向的元素,返回一个指向被删元素之后元素的迭代器,这时不能在自增了,因为迭代器指针已经指向下一个元素了,如果在自增,就将被删除的元素的后面一个元素就跳过去了,如果在被删除的元素在末尾,那么迭代器指针就会变成野指针。

(27)虚函数和纯虚函数的区别?

虚函数

引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。

纯虚函数在基类中是没有定义的,必须在子类中加以实现。

纯虚函数

引入原因:在很多情况下,基类本身生成对象是不合情理的。

纯虚函数就是基类只定义了函数体,没有实现过程,定义方法如下;

virtual void Eat() = 0; 直接=0 不要 在cpp中定义就可以了。

纯虚函数相当于接口,不能直接实例话,需要派生类来实现函数定义。

虚函数在子类里面也可以不重载的;但纯虚必须在子类去实现,

普通成员函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数;虚函数为了重载和多态的需要,在基类中定义的,即便定义为空;纯虚函数是在基类中声明的虚函数,它可以再基类中有定义,且派生类必须定义自己的实现方法。

一旦父类的成员函数声明virtual,其子类的函数不管有没有声明为virtual,都是虚函数。

普通函数如果不被使用,可以只有声明没有定义,虚函数必须要有定义,即使是一个空实现,因为编译器无法确定会使用哪个函数。

(28)C++中overload,override,overwrite的区别?

Overload(重载):在C++程序中,可以将语义、功能相似的几个函数用同一个名字表示,但参数或返回值不同(包括类型、顺序不同),即函数重载。
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。

Override(覆盖):是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。

Overwrite(重写):是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

(29)C++中四种强制类型转换 ?

去const属性用const_cast。

基本类型转换用static_cast。

多态类之间的类型转换用daynamic_cast。

不同类型的指针类型转换用reinterpret_cast。

(30)有了malloc/free,为什么还要new/delete?

malloc与free是C/C++的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象的消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

因此,C++需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意:new/delete不是库函数。

(31)map可以用结构体作为键值吗,注意事项?

在使用map时,有时候我们需要自定义键值,才能符合程序的需要。

比如我们需要使用自定义的结构体来作为map的键值。

键值无法比较。因为map的键值是自动比较后进插入的,键值是递增的。

现在我们自定义的键值,编译器无法进行比较,找不到类似的模板,所以报错。

既然是没有‘<’,那我们自己重载小于操作符应该就可以了。

(32)Volatile的作用?

voliate变量是随时变化的,用voliate修饰的运算,编译器不进行优化,以免出错。

对于一个普通变量,为提高存取速率,编译器会先将变量的值存储在一个寄存器中,以后再取变量值时,就存寄存器中取出。

但是用voliate修饰的变量,就说明这个变量会发生意向不到的改变。也就是说,优化器每次在读取该值时,不会假设这个值了,每次都会小心的在读取这个变量的值,而不是在寄存器中取保留的备份。

那么,一个参数可以同时被const和voliate修饰吗?
答案是可以的,如:只读的状态寄存器。它是voliate,是因为它可能会发生意想不到的改变;它是voliate,表示程序不应该试图去改变它。

(33)了解哪些C++11特性?

https://blog.csdn.net/chen134225/article/details/80976666

(34)右值引用和move语义?

不知道

(35)STL里resize和reserve的区别?

  • size():返回vector中的元素个数
  • capacity():返回vector能存储元素的总数
  • resize()操作:创建指定数量的的元素并指定vector的存储空间
  • reserve()操作:指定vector的元素总数

resize():改变当前容器内含有元素的数量(size()),eg: vector<int>v; v.resize(len);v的size变为len,如果原来v的size小于len,那么容器新增(len-size)个元素,元素的值为默认为0.当v.push_back(3);之后,则是3是放在了v的末尾,即下标为len,此时容器是size为len+1;

reserve():改变当前容器的最大容量(capacity),它不会生成元素,只是确定这个容器允许放入多少对象,如果reserve(len)的值大于当前的capacity(),那么会重新分配一块能存len个对象的空间,然后把之前v.size()个对象通过copy construtor复制过来,销毁之前的内存;

只有当容器内元素数(size)大于capcity时,容器才会改变地址。

(36)vector和deque的区别?

vector是单向开口的连续线性空间, deque是一种双向开口的连续线性定 ;

deque允许于常数时间内对起头端进行元素的插入或移除操作 ;
deque没有所谓容量(capacity)观念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。

(37)不同排序算法的比较?

在这里插入图片描述

(38)大端和小端的区别,以及如何判断一台机器是大端还是小端?

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
int checkCPU()
{
    union w
    {
        int a;
        char b;
    }c;
    c.a = 1;
    return (c.b == 1);//小端返回1,大端返回0
}

(39)malloc分配内存的原理?

步骤分为放置、分割和合并

在堆中,堆块由一个字的头部、有效载荷、填充以及一个字的脚部组成,空闲块是通过头部中的大小字段隐含地连接在一起形成一个隐式空闲链表,分配器可以通过遍历堆中所有的块,从而间接遍历整个空闲块的集合。

1、放置已分配的块

当一个应用请求一个k字节的块时,分配器搜索空闲链表,查找一个足够大可以放置所请求块的空闲块,分配器执行这种搜索的方式是放置策略确定的。常见的策略是首次适配、下一次适配和最佳适配。

首次适配:从头开始搜索空闲链表,选择第一个适合的空闲块。

下一次适配:从上一次查询结束的地方开始搜索空闲链表,选择第一个适合的空闲块。

最佳适配:检查每个空闲块,选择适合所需请求大小的最小空闲块。

2、分割空闲块

一旦分配器找到一个匹配的空闲块,它就必须做另一个策略决定,那就是分配这个空块中多少空间。一个选择是用整个空闲块,另一个选择是将这个空闲块分割成两部分。

如果分配器不能为请求块找到合适的空闲块将发生什么呢?一个选择是通过合并那些在内存中物理上相邻的空闲块来创建一些更大的空闲块。然而,如果这样还是不能生成一个足够大的块,或者如果空闲块已经最大程度地合并了,那么分配器就会通过调用sbrk函数,向内核请求额外的堆内存,分配器将额外的内存转化成一个大的空闲块,将这个块插入到空闲链表中,然后将被请求的块放置在这个新的空闲块中。

3、合并空闲块

Knuth提出了一种聪明而通用的技术,叫做边界标记,允许在常数时间内进行对前面的块合并。这种思想是,在每个块的结尾处添加一个脚部,其中脚部就是头部的一个副本,如果每个块包括这样一个脚部,那么分配器就可以通过检查它的脚部,判断前面一个块的起始位置和状态,这个脚部总是在当前块开始位置一个字的距离。

(40)为什么构造函数不能声明为虚函数,析构函数可以,构造函数中为什么不能调用虚函数?

1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。

2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。

(41)STL中unordered_map 和 map的区别 ?

一、hash_map与unordered_map

这两个的内部结构都是采用哈希表来实现。区别在哪里?unordered_map在C++11的时候被引入标准库了,而hash_map没有,所以建议还是使用unordered_map比较好。

哈希表的好处是什么?查询平均时间是O(1)。顾名思义,unordered,就是无序了,数据是按散列函数插入到槽里面去的,数据之间无顺序可言,但是有些时候我只要访问而不需要顺序,因此可以选择哈希表。举个最好的例子,就是我的LeetCode的博文里——Longest Consecutive Sequence这一题,我的方法二就是用的unordered_map来实现“空间弥补时间”这样的做法。

二、unordered_map与map

虽然都是map,但是内部结构大大的不同哎,map的内部结构是R-B-tree来实现的,所以保证了一个稳定的动态操作时间,查询、插入、删除都是O(logn),最坏和平均都是。而unordered_map如前所述,是哈希表。顺便提一下,哈希表的查询时间虽然是O(1),但是并不是unordered_map查询时间一定比map短,因为实际情况中还要考虑到数据量,而且unordered_map的hash函数的构造速度也没那么快,所以不能一概而论,应该具体情况具体分析。

三、unordered_map与unordered_set

后者就是在哈希表插入value,而这个value就是它自己的key,而不是像之前的unordered_map那样有键-值对,这里单纯就是为了方便查询这些值。我在Longest Consecutive Sequence这一题,我的方法一就是用了unordered_set,同样是一个将空间弥补时间的方法。再举个大家好懂的例子,给你A,B两组数,由整数组成,然后把B中在A中出现的数字取出来,要求用线性时间完成。很明显,这道题应该将A的数放到一个表格,然后线性扫描B,发现存在的就取出。可是A的范围太大,你不可能做一个包含所有整数的表,因为这个域太大了,所以我们就用unordered_set来存放A的数,具体实现库函数已经帮你搞定了,如果对于具体怎么去散列的同学又兴趣可以查看《算法导论》的第11章或者《数据结构与算法分析》的第五章,如果要看《算法导论》的同学我给个建议,完全散列你第一遍的时候可以暂时跳过不看,确实有点复杂。

(42)C/C++中extern的用法 ?

在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。

1:extern修饰变量的声明。举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。

2:extern修饰函数声明。从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。

使用extern和包含头文件来引用函数有什么区别呢?
extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

3:此外,extern修饰符可用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。

(43)I/O模型

https://blog.csdn.net/chen134225/article/details/81749980
(44)TCP和UDP的应用场景,从生活中使用的APP的一些例子来讲。

当对网络通信质量有要求时,比如:整个数据要准确无误的传递给对方,这往往对于一些要求可靠的应用,比如HTTP,HTTPS,FTP等传输文件的协议,POP,SMTP等邮件的传输协议。常见使用TCP协议的应用:
1.浏览器使用的:HTTP
2.FlashFXP:FTP
3.Outlook:POP,SMTP
4.QQ文件传输

对当前网络通讯质量要求不高的时候,要求网络通讯速度尽量的快,这时就使用UDP
日常生活中常见使用UDP协议:
1.QQ语音
2.QQ视频
(45)判断两个链表是否相交。

1.判断两个链表最后一个结点是否相同。

2.将第二个链表的头结点接在第一个链表的尾结点后,判断合成的链表是否形成了环。
(46)二叉树的广度优先遍历和深度优先遍历。

//深度优先搜索
//利用栈,现将右子树压栈再将左子树压栈
void DepthFirstSearch(BitNode *root)
{
    stack<BitNode*> nodeStack;
    nodeStack.push(root);
    while (!nodeStack.empty())
    {
        BitNode *node = nodeStack.top();
        cout << node->data << ' ';
        nodeStack.pop();
        if (node->right)
        {
            nodeStack.push(node->right);
        }
        if (node->left)
        {
            nodeStack.push(node->left);
        }
    }
}

//广度优先搜索
void BreadthFirstSearch(BitNode *root)
{
    queue<BitNode*> nodeQueue;
    nodeQueue.push(root);
    while (!nodeQueue.empty())
    {
        BitNode *node = nodeQueue.front();
        cout << node->data << ' ';
        nodeQueue.pop();
        if (node->left)
        {
            nodeQueue.push(node->left);
        }
        if (node->right)
        {
            nodeQueue.push(node->right);
        }
    }
}

(47)快排,堆排,归并哪些是稳定的,假如我要用C++封装一个sort我要用那种比较好。

只有归并是稳定的,封装的话看需求。
(48)现在有一百万个数不重复我要使用那种排序最快最好。

内存足够,快速排序。

内存不够,多路归并排序。

1.静态变量跟普通变量的区别
2.静态函数跟普通函数的区别
3.进程和线程
4.线程间通信
5.互斥锁和信号量的区别
6.传递函数时,传递指针和传递指向指针的指针
7.在函数里定义数组,可以返回该数组名么
8.堆和栈的区别
9.数组和链表
10.链表的逆序
11.链表的内容
12.utf-8和Unicode
13.宽字符

 

一面(问基础知识):
自我介绍;
介绍完开始问基础
排序算法有哪些,复杂度
复杂度相同,快排的优势
讲一下STLvector list 等的底层实现
存放数据量比较大的时候选择vector还是list,数据量比较小的时候呢
栈和队列的区别
死锁的条件
进程线程优缺点
进程通信方式
类成员访问控制方式有哪些(private和protected区别)
常用设计模式讲一下
malloc和new的区别
快排思想
二面:(一面完10分钟左右继续)
进程的状态
死锁的条件,解决死锁的方法
问了三个算法没听过,直接回答不会
讲一下内存管理,自由存储区是什么
malloc内存分配底层操作,用malloc分配内存1k和100M有什么区别
TCP三次握手和四次挥手
三次握手过程中做了哪些准备(没答好)
为什么有TIME_WAIT
设计抢红包算法(一直问问了很多)

1.局部变量,全局变量,分别存在内存哪个位置
2.程序内存的分布,五个部分
3.new,malloc区别
4.数据结构相关问题,闲聊
5.C STL了解,说说vector,list,map区别
6.分析他们的性能
7.TCP三次握手,两次为什么不行
8.TCP,UDP区别
9.进程通信的几种方式(管道,有名管道,信号,信号量,共享内存,消息队列,套接字)
10.分析他们的区别,用于那些场景
11.链表倒数第k个数,程序思路
12.快排思路
没有手撕代码
等了一会然后通知二面
二面技术面,首先自我介绍,然后介绍项目
项目里面有多线程然后一直追问细节,二面一点紧张,答得不好。
1.项目里面用到了C 什么新特性(太抽象,答得很差)
2.堆栈的区别
3.TCP,UDP了解多少
4.B-树,B 树区别和原理,效率,应用场景,写过代码没,项目里面有没有用到(不会,没有用到)
5.项目里面除了vector还用到那些数据结构
6.红黑树

作者:从0开始学c
链接:https://www.nowcoder.com/discuss/128236
来源:牛客网

然后问算法,问了反转链表,要求空间复杂度o1,我在循环内用了一个局部指针变量,虽然不优雅,但是局部变量每次循环完都会被析构,他硬说我的空间复杂度是on。

然后问了虚函数,这是唯一问的c++,我感觉他也就会个虚函数了。

然后问找前k大的数。

我: 如果内存放得下的话,用类似快排的思想,partition把大的放左边,小的放右边,调用partition之后,如果分界元素等于k,则返回最左边的k个值;否则对k所在的半边递归调用parition,平均时间复杂度是on。

面试官(惊讶): 时间复杂度是on?

我: 是啊

面试官: 真的是么?

我: 是啊,假如每次分界完,平均下次要处理的元素占总元素数的a/b,那么时间近似是(1+a/b+(a/b)^2+…)n= b/a*n

面试官: 那我的k要是很大,接近n,你这个不就是n平方了么

我: a/b是平均下次要处理的元素占本次处理的总元素的比值,跟k无关

面试官: 那最坏时间复杂度是多少

我: on^2 当数组已经有序,每次处理完规模减少1。 如果你觉得这个方法不好,在内存放得下的情况下,那我们用堆做,建一个最大堆,建堆的时间复杂度是on,调整k次,调整一次的时间复杂度是ologn,一共是o(n+klogn)

面试官: 建堆的时间复杂度是on?

我: 有什么疑问么

面试官: 你确定?

我: 确定!

面试官: 你再想想?

我: 建堆是从最后一个非叶结点开始调整,倒数第二层最多有n/2个需要调整的元素,最多需要调整1次,倒数第三层最多有n/4个需要调整的元素,每个最多需要调整2次,以此类推,最后累加起来接近线性时间复杂度。

面试官: 额…

我: 换一种方法,如果数据比较大,内存放不下,可以用优先队列,实现也是堆。优先队列是用一个最大堆,我们求前k大要用最小堆,所以要重载小于号运算符,优先队列重载时候要指定底层容器,我一般指定的是vector。执行时候如果队列里面的元素少于k个,则直接插入;否则将该元素与top()比较,如果大则删掉top把这个元素放到队列中。

面试官:额..

我: 如果重复元素算一个,就用set,set是默认从小到大排列的,所以不需要重载运算符。

然后面试官没有回话,思考了一会,用“你会数据库么”结束了对算法的问询。在得知我不会数据库之后,面试官开始了他的主导,一直问数据库。我说,我不会数据库,要不你问问别的吧。然后他问我会网络么,我说曾经会一些,很久没用了,于是就问我tcp连接的终止,在我答完四次握手之后,问我服务器单方面终止链接之后,客户端继续发送数据会怎么样; 双方都终止了之后,客户端继续向服务器发送数据会怎么样。
如何处理get和post
tcp接收窗口和拥塞窗口
什么时候会向对端传窗口大小
extern C的意义
假设rtt(数据从两端一来一回) 100ms,那么从输入一个http://url到得到网页要多少时间
https呢?
连续发送两次http请求,会得到两次结果吗?可能第二次比第一次快吗?
是否了解TCP包头阻塞?
服务器状态502 503 504什么问题,怎么排查
netstat具体查看什么问题
写题:多路归并(用了堆,在细节上有一些问题)
看代码中的问题:
class Foo
{
public:
Foo(){_p = new int();}
~Foo() {delete _p; _p = nullptr;}
private:
int* _p;
}
sql:三句查询,要求建立索引来优化查询
一些linux语句的作用:less more sed awk du df dd at tee crotab xargs
最近看了什么技术书籍

二面
linuxIO模型,区别在哪
线程独立拥有哪些资源
协程和线程有什么差别,优势呢?
get和post有什么差别
sendfile的优势在哪?
代码:随机播放100首歌(洗牌算法/这个我把自己绕进去了,洗一次直接输出就完了,我当时脑子短路了,洗一次播一首非要再洗一次来手动提升复杂度,最后没绕出去,然后换题了)
两个倒序数组找最第k大的(框架差不多,最后发现漏了一种情况,感觉还在想洗牌的事情)

因为二面代码花了很久,最后没写完,当时心态有点崩,但给了三面

三面
三面没有写代码,问了一个小时,面试官全程半启发半追问,感觉有点懵,我把上下文相关的问题空格分段了

C/C++内存问题有哪些,尽量说
free和delete在具体实现上的差异
free之后的指针使用有什么问题
缓冲区溢出如何避免,有哪些场景
如何检查/处理越界
野指针和悬空指针分别是什么
试图使用野指针有什么问题
内存上还有别的问题吗?

C++11用过什么特性

之前讲的内存问题有什么好的方法吗?
智能指针讲一下
shared_ptr讲一下,怎么实现的,unique_ptr呢?
是不是所有要用指针的地方都应该用智能指针,有什么问题和不足?(我答了两次寻址和额外空间)
这些缺陷,在不用shared_ptr的前提下有减少成本的策略吗?(跳过了)

include,头文件里面一般放了些什么
声明和实现要写在一起吗?是不是一定要分开写?
写在一起和分开对最后的代码有什么影响,怎么确认(这个我不会,面试官让我试着分析一下,结合include的行为来谈)
gdb怎么查看一个函数的地址?
你在Linux使用经常哪些指令
如何探查CPU负载情况
在什么时候CPU被认为是繁忙/空闲的?

看过哪些比较大的代码?(后面很多问题是从这来的)

服务器:
多线程服务器和nginx在工作方式有什么不一样的地方
nginx怎么处理请求
进程唤醒(惊群问题)的额外成本主要在哪?
nginx的负载均衡(我只答了那个worker的负载均衡)
为什么它要用多进程,优势在哪,劣势在哪
多线程怎么应付同样的问题,能够解决吗,讲一讲方案
你的方案有什么问题?

http了解多少?
http缓存机制了解吗?
长连接讲一下
如何实现长连接(保活)
带外数据如何使用?
你的这个方法有什么问题,可以直接兼容不同的浏览器吗?
了解nginx的解决方案吗?

redis
你对redis怎么理解的?
redis的总体结构
单线程的优势和缺点
redis的事件分发
讲一讲文件事件有哪些
client功能是怎么实现的
时间事件(serverCron函数)
serverCron做了什么
redis所有事情都只有一个单线程吗?
bgsave讲一下,为什么要fork一个进程来做

interrupt与signal有什么差别
interrupt的发起和接受者是谁
操作系统在interrupt中发挥了什么作用
signal呢,发起者又是谁,接收者呢?(这里答得有点混乱)

TCP
ack什么时候发送,丢失了会怎么样?
sack了解吗?
重传ack的时机只有ack超时吗?
重复报文被接收会发生什么?
拥塞窗口要不要把自己的大小发给接收方,意义何在?(这个问题一面也问了,没有答出来)
延迟ACK的意义在哪?
为什么不能每次都直接发大的窗口?

进程地址空间布局讲一下
BSS为什么要叫这个名字?(后来查了,block started by symbol)
static关键字有什么作用,如果用来修饰函数呢?
多个线程使用static数据会开启多个副本吗?

C++OO
多重继承怎么实现
虚拟继承怎么实现
对于函数寻址在时间成本上有什么差异?
对于继承体系很复杂的情况这个成本会被拉高吗?

 

算法:
1. 两个相交的单链表,找出交点
2. 给一棵树,找出路径和为n的路径
基础:
1. static关键字
2. 在一个函数内定义一个static对象,什么时候构造和析构。如果这个函数从没被调用,会怎么被析构
3. tcp连接和断开
4. 服务器大量close_wait状态,可能是什么原因,怎么解决
一面还有很多问题的,忘了。。。
一面感觉:那个两个相加的单链表的算法,我提出的算法他没见过,然后我证明,然后balabala说的不好,然后跳了。。。
这也是一面唯一一个感觉面的不好的地方
二面:
1. 设计LRU cache,查找复杂的O(1), 过期淘汰
数据库:
2. 联合索引, 最左匹配
3. 假如有联合索引<a,b>,查询where a=xx and c == yy,会用到联合索引么 为什么
4. 如果数据库主键是单调严格递增的,有一个图片,通过url带上id访问,然后查询数据库,会有什么影响
5. 上面那个问题,引出一个情景题,如何设计一个序列生成器,能够单调递增,但是不是严格递增的 ?保存在内存中,宕机怎么办?多个进程怎么办?
这个问题和面试官聊了很久,因为我在微信这边不久前看到过序列生成器
6. 解决并发情况下,使序列生成器生成的id唯一。还有就是在分布式系统,多机服务器怎么办?
7.
long multiply(int m,int n) {
long score;
score = m * n;
return score;
}
这段代码会有什么问题? 然后就说了一下m*n溢出
8.
请问下面的程序一共输出多少个 “-”?,执行一次下面的程序,总共生成了多少个进程?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
int i;
for(i=0; i<2; i ) {
fork();
write(1, “-“, 1);
}
wait(NULL);
wait(NULL);
return 0;
}
我说了6次,然后解释了一遍
9. 然后说把write换成printf会多少个’-‘, 我算了一下,说8次,原因是printf是有缓存的
10. c语言程序的内存模型
11. 聊redis , 如果内存已经很多键了,会怎么样?然后说了一下cow 还有balabala
还有一些小问题完了
二面总结:最后的redis因为时间不够,然后面试官说结束了。感觉二面面的挺好的,和面试官聊的也很多
三面:
三面一看就是大佬,他一直在看我的简历,开始那7分钟,大家一句话都没说,很尴尬
1. 写sql
Sid:学号
Cid:课程编号
score:成绩
查询平均成绩大于 60 分的同学的学号和平均成绩
2.
void pass(){
}
int main( ) {
int x;
x = 123;
printf(“%d \n”,x);
pass();
printf(“%d \n”,x);
return 0;
}
// 123
// 456
他问在pass里面添加代码,使输出123和456
因为都在栈里面,有返回地址,占四个字节
void pass(){
int y;
int *addr = &y;
addr 加加  ;
addr加加   ;
*addr = 456;
}
大概思路是这样, 细节有待斟酌
算法题:
3.
随机数生成器:
float rand(); [0,1)
int rand5();
int rand7();
这个通过rand,然后写出rand5,最后写出rand7。面试官刚开始说rand返回[0,1),然后让我写代码验证,
我心里一凉,是不是写错了。果然跑的结果不对,然后现场debug,rand返回的是一个unsigned int,根本不是[0,1),
然后改好了
4. 写一个函数,N 个数字,找到其中第 K 大的数,要求平均时间复杂度尽量低。
我写出来后他让我算时间复杂度,时间复杂度一直没算对,还用了主定理。 作为一个理科生,最后时间复杂度要数列求和,没求出来,很惭愧
5.http状态码
tcp的连接,怎么用udp模拟tcp
数据库索引了解吗(b 树)
那为什么用b 树,有什么优点呢

多态,虚表虚指针,虚基类以及内存分布

函数重载
构造函数和复制构造函数能否为虚,为什么
一个对象的内存分布,多个虚函数占多大空间
shared_ptr介绍原理,weak_ptr如何解决引用传递
右值引用
编译器如何处理模版
编译中的导出符号表和未决符号表
反汇编时符号表的状态
比较c++和java
介绍一下stl的list,查找list复杂度
unorder_map插入复杂度
stl迭代器重载
遍历vector的几种写法
数据库常用数据结构,b+树的好处
图的bfs和dfs
快排,复杂度,最坏情况以及设计算法解决
tcp和udp
如何用udp封装实现tcp
进程和线程
如何保证线程安全
互斥锁原理和使用

1、inline的用法?

2、class A

{

int a;

short b;

int c;

}

sizeof(A)的大小?类中加上double d;呢?

3、你知道什么排序算法?它们的平均复杂度各是多少?其中稳定的排序有哪些?

4、说一下快排。它的最坏复杂度是多少?什么情况下最坏?

5、说一下归并?

6、哈希是什么?哈希如何存储数据?什么情况下用到哈希?

7、说一下static的作用?

8、虚函数你知道吗?它是如何实现的?

9、如何让一个类被有限次数的实例化?

10、纯虚函数是什么?如何定义?

11、一个类如何被称为抽象类?抽象类可以实例化吗?为什么?

12、如何比较两个对象?

13、跳台阶,一次跳1阶或2阶,n阶有多少种跳法?(最多能跳n阶呢?)(动态规划,递归)

14、一个链表,实现它的翻转。(当时定义了三个指针, = =反正挺简单的)

15、有一个数组,所有数据都可以是负数、0、正数,求和最大的连续序列。如果是一个矩阵呢?(矩阵的没答上)

16、stl库懂吗?你常用的有什么?

17、vector的底层是什么?它是如何实现动态分配空间的?如果将其中一个元素删除,那么它的地址空间是怎么样的?

18、map、set知道吗?(知道,底层红黑树。既然你说到红黑树,那说一下红黑树是什么?它的实质是什么?如何实现的?)说一下它们的区别?

19、线程和进程的区别?线程间如何通信?线程共享的资源有什么?

20、TCP和UDP的区别?TCP如何实现可靠传输?它们的传输方式?

21、socket懂吗?如何实现?

22、堆和栈的区别?
二面(可能有一些在上面,具体也记不清了):

23、给你一串字符串,压缩它有几种方法?

24、vector赋值n个数,它需要拷贝几次?

25、基类A,派生类B继承于A,A *a = new B[10]是否正确?会发生什么错误?a[5]能正确的取到对象吗?

26、两个链表,判断他们是否有相交部分?如果他们相交部分有环呢?

27、一副扑克,如何等概率洗牌?不消耗额外空间呢?

一面:
似乎是个不太厉害的面试官,只会问一些套路问题,一开始在纸上写好了一堆考察C++的笔试题,然后让你现场答。
有点印象的记得问了一些指向函数指针的数组怎么写?
char a[] = “test” char b[] = “test”
char *p = “test” char *t = “test”
a==b ?
p==t ?
然后基本一直考察算法:
二叉树非递归中序遍历。
讲一下因为保密协议不能说的笔试题(我觉得巨简单,然而一面面试官似乎并不能轻松看懂我的代码,现在回想起来感觉对网易的技术印象有点降低了)
一个ip地址段(由首地址ip和尾地址ip组成,保证连续)表,怎么找到一个ip属于其中哪一个地址段? (因为ip段不重合,根据首地址排序后二分找就可以了,感觉这题有点迷之简单。)
然后面试官就问ip段重合怎么办?然后当时没想出来,问题转化成查询覆盖一个点的所有线段。
二面:
这次还是有点分量的面试官。
一边充当hr一边充当面试官。
一致性哈希。
手撕智能指针。
给一个情景题,设想产生很多要求保序的请求从多个机器上发到一个多线程的代理上,再由代理调用分布式的数据库,怎么保证这个过程中的顺序不乱。
然后开始继续怼算法:
求一个数组左边之和最接近右边之和的节点。我想的是用前缀和来搞。
求中位数。
求一个流动数组的中位数,每次加入元素都要返回中位数,两个堆解决。

1,c++多态的实现。讲了c++虚函数表,单继承,多继承,虚继承以及为什么虚继承,调用过程
2,智能指针。
3,熟悉stl的什么结构。我说的是看过sgi 的stl源码。就问了什么情况用vector什么情况用list,
以及vector的insert,erase,remove的实现还有重新申请内存的情况

1.Base类有test方法,Base的不同对象调用test方法,内部是怎样的呢?(我答的指向同一个预先分配好的地方)

2.有一个AnotherBase类(与Base无关系)里面也有一个test方法,用其强制转换Base的对象,再调用这个对象的test方法,请问调用的是哪个类的方法?
3.在方法func()后面加const意味着什么?
4.给一个六面骰子,如何做出一个1~10的等概率随机方法?
5.用过什么设计模式?

  • C 和 C++ 的区别
  • new 和 malloc的区别
  • 对虚函数的理解
  • 多线程的理解(多线程同步的途径)
  • 多进程(继承什么, 不继承什么)
  • 进程间通信
  • gdb的使用, 编译器的使用
  • MySQL 查询前 100 条数据, 以及如何分组
  • 常见的Linux的命令
  • TCP和UDP的区别
  • socket的流程
  • 五种IO模型
  • linux基本操作
    • 拷贝文件 、查看ip、vim的基本操作(查找字符串、替换字符串)、gdb的调试;
    • 查看硬盘大小等等操作
    • 总结需要详细的看看linux的基本操作命令等(这部分很尴尬都不会)
  • STL
    • vector与list的区别
      • 怎么查找倒数第二位数字;
      • 二者的区别;
    • map怎么插入数据 有几种方式
      • 每种方式的优缺点;
  • 多线程多进程
    • 线程间同步的方式 :我答了 信号量、互斥量;问我还有没有 我说我记得就这几个了
    • 然后问我进程间同步的方式 答了一个临界区 ;忘了信号量和互斥量和事件了;
    • 然后我自己抢答了 进程间通信的方式:说了之后然后问我几个问题
      • 怎么创建管道 pipe()
      • 怎么创建共享内存shmget();
        1.自我介绍
        2.用过linux系统吗,哪种linux系统,版本呢?
        3.linux基本命令。怎么查看IP;怎么给文件改名;怎么查看文件的权限;修改权限;怎么加执行权限;怎么查看当前系统的版本;怎么查看当前系统硬盘空间的总量与使用情况;怎么查看系统内存多少;怎么查看某个命令执行的时候需要链接哪些系统库;怎么给一个文件做一个软链接;说一下gdb;怎么把一个test.cpp编译成一个test.so;
        4.vector与list的区别
        5.怎么找某vector或者list的倒数第二个元素
        6.说一下map和set的区别
        7.红黑树的原理
        8.map怎么插入数据,有几种方式
        9.c++11在原来的版本上都加了哪些东西。
        10.智能指针,三种指针都介绍一下其特性,作用。
        11.进程怎么同步,线程怎么同步,要说全。
        12.tcp与udp的区别,udp怎么实现多对多通信,问的很细,包括tcp的各种机制。
        13.说一下快排
        14.QT的信号槽是什么原理。

        C++基础

        • 自我介绍
        • 平时有用C++写过项目吗?(这里没让我展开说项目)
        • 对C++的特性有什么了解
        • 对封装、继承、多态的具体理解
        • public/protected/private的区别
        • 说一下三种方式继承对基类的访问权限
        • 说说构造函数的执行顺序,析构函数呢
        • 说一下构造函数内部干了什么
        • 如何实现多态
        • 构造函数和析构函数可以调用虚函数吗,为什么
        • 析构函数一定要是虚函数吗,为什么
        • 怎么理解C++的面向对象和C的面向过程
        • 可以介绍一下new的实现原理吗
        • new和malloc的异同处
        • C++怎么为各种变量分配内存空间的
        • 引用了解吧,介绍一下
        • 拷贝构造函数内部做了什么,什么时候需要重写
        • 初始化列表了解吗(以为是那个C11特性,没敢说)
        • 平时用什么编程环境(Windows+MFC+Qt)
        • 用过Qt是吧,说一下信号和槽的机制,绑定的方式
        • 你觉得MFC和QT比各自有什么优缺点
        • MFC的消息机制和Qt消息机制的对比

        进程线程相关

        • 了解过线程吗,谈一下进程和线程的联系和区别吧
        • 对于共享的区域多个进程或线程一起访问会不会出问题,要怎么解决(同步和互斥)
        • 进程通信有哪几种方式,介绍一下

        网络(项目里有)

        • Socket的流程是什么样的(服务端和客户端两个)
        • 项目里用的什么协议(TCP)
        • TCP和UDP的区别,优缺点

        数据库

        • 你这项目的数据库自己设计的吗,简单介绍一下你的设计流程
        • 了解数据库范式吗,介绍一下
        • 用过索引是吧,说一下索引的优缺点,选取条件
        • 数据库里多对多关系怎么处理设计

        数据结构

        • 说说vector和list的不同,优缺点
        • 平衡二叉树了解吗,说说它的特点,时间复杂度(logN)
        • 说说二叉树的三种遍历(想让我写来着,没带纸笔,口述了算法思想和区别,递归和非递归)
        • 图了解吗,说一说它的遍历(广度和深度)

        回到C++

        • 说说宏定义和const的区别
        • 宏定义和内联函数的区别
        • 内联函数的作用,和普通函数有什么区别
        • C++有几种转换方法,简单介绍一下
        • 重载是什么,和重写有什么区别