C++复习笔记

[toc]

记录一些容易忘记的C++知识

C++知识体系较为庞杂,学得不够系统,对知识点进行记录和定期复盘是很有必要的。现在想重新过一遍《C++ Primer Plus》,把一些被遗忘了的和还未学习的知识记录下来,方便日后查阅。

正篇开始

1. 头文件

C语言的头文件使用扩展名.h,C++则没有扩展名,但仍然可以使用C语言的.h文件。有些C头文件被转换为C++头文件,并被重新命名,去掉了扩展名.h,并在文件名称前面加上前缀c,例如,C++版本的math.hcmath。没有.h扩展名的头文件可以包含名称空间。

2. 函数

  1. C/C++不允许将函数定义嵌套在另一个函数定义中;

  2. 在C++中,不指定参数列表时应使用省略号void func(...){ },通常,仅当与接受可变参数的C函数交互时才需要这样做;

  3. C++函数不能直接返回数组,但可以将数组作为结构或对象的组成部分来返回;

  4. 函数返回对象时,有可能使得下面的代码能够通过编译:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Vector v1, v2;
    Vector v3;

    // 重载加法运算符
    Vector Vector::operator+(const Vector & rv)
    {
    return Vector(x + rv.x, y + rv.y);
    }

    v3 = v1 + v2; // 正常使用逻辑

    v1 + v2 = v3; // 能够通过编译,先执行operator+,再执行operator=

    为防止在使用赋值运算符的时候出错,可以把返回值设置为const类型。

  5. 传递数组:

    1
    2
    3
    4
    5
    6
    int sum(int [], int);  // 函数原型
    int sum(int *, int); // 另一种形式
    int sum(int array[], int n){return 0;} // 函数定义,sizeof array将等于指针类型长度

    /*为防止函数无意中修改数组的内容,可在声明形参时使用关键字const*/
    int sum(const int *, int); // 这表明该形参指针指向的是常量数据,不允许通过该指针进行修改
  6. 函数不能返回字符串,但是可以在函数体中申请内存空间,返回该内存空间的地址,以此来返回一个字符串;

  7. 函数的地址:

    函数的地址是存储其机器语言代码的内存的开始地址。==函数名==就是函数的地址。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 声明函数指针
    double (*pf)(int); // 可以首先编写函数的原型,然后用(*pf)替换函数名

    // 通过函数指针调用函数
    double y = (*pf)(x);
    double y = pf(x); // C++中也允许像使用函数名那样使用pf

    /*声明函数指针数组,运算符[]的优先级高于*,所以pf[3]表明其是一个包含三个元素的数组,*pf[3]表明其是一个包含三个指针的数组,其他部分的内容则说明这些指针是函数指针。此处不能使用auto关键字,因为自动类型推断只能用于单值初始化,不能用于初始化列表。但是声明数组pf后,可以使用auto来声明同类型的数组
    */
    const double * (*pf[3])(const double *, int) = {f1, f2, f3};
    auto pa = pf;
    pf[0](cpd, 3); // 通过函数指针数组和索引调用函数

    const double * (*(*pd)[3])(const double *, int) = &pf; // 指向函数指针数组的指针,我的天呐

    /*使用typedef进行简化*/
    typedef const double * (*p_fun)(const double *, int);

    p_fun p1 = f1; // 声明函数指针变量,p_fun为新类型的别名
    p_fun p2[3] = {f1, f2, f3}; // 创建函数指针数组,很方便
    p_fun (*pd)[3] = &f1; // 创建指向函数指针数组的指针

    Read More

长征五号遥三运载火箭纸模型制作

长征五号遥三运载火箭纸模型制作

大概是2020年的六月份,因为太久没有折腾点东西了,手痒,急需一个新作品让动手能力有地方可以输出。我一直很想做一个机械臂,但是太烧钱了,整不起。无意间在B站看到有UP主做火箭的纸模型,细节拉满,一看就很考验动手能力,并且成本低廉,是个相当不错的选择。

这里要感谢黄开大佬设计并分享出来的模型:

Read More

丘比特之箭

丘比特之箭

大二的时候,在南科大读书的朋友给学校设计了一块RGB灯牌,看完他QQ空间发的作品图,我也很想自己做一块玩玩。

照抄就没意思了,咱得弄点有新意的。我打算设计成一支箭穿过字母LOVE的形状,最后的成品应该会比较惊艳。

先开始画原理图:

Read More

大学与四轴飞行器

大学与四轴飞行器

高中那一会就很喜欢航模,但是那会穷得叮当响,也只能是做做白日梦。等熬到了大学,情况就稍微好一些了。

大一刚上学的时候,就敢跑去和校园京东派谈合作,说我想要钱造飞机,我们出去飞飞机的时候,可以把宣传标语印在飞机上。后来事情没成,什么原因,太久了也忘了。

慢慢地,我也认识了一些同样喜欢航模的朋友。印象中先是认识了一个老乡,他高中就开始玩了,玩固定翼也玩直升机。后来他在学校遇到另一个也玩飞机的朋友,就介绍给我认识,听到他是美术学院的,我当时还很诧异,美术学院的拿电烙铁确实很酷。

可是我穷啊,穷到一架KT板固定翼都攒不出来。当时是打算跟一好哥们一块出钱拼一架飞机的。我在淘宝上看中一架三角翼,当时觉得颜值很高,非常心动,但是其实就是一块有贴纸的KT板,非常的脆,很不耐炸的。我忘了最后是我付款还是哥们付款的,反正最后飞机没拼成,似乎连电机都没有,很多事现在都记不起来了,但是应该也是没钱的缘故吧,大学太卡钱了。

我也想要有自己的飞机啊,和他们出去玩的时候我总是只能干看着,我不敢玩他们的飞机,怕炸机了赔不起。所以,我到现在还是不会飞固定翼。后来他们开始玩起穿越机了,我想,我要不自己画个PCB四轴飞行器吧,可以省点钱,这样也可以有架自己的飞机。我找来了一本关于制作PCB四轴飞行器的书,然后在淘宝上选空心杯电机、螺旋桨、锂电池、和电位器摇杆等等配件。那时候还是第一次学习PID,第一次看到PID在程序里面是怎么实现的,原来,对于四轴飞行器来说,就是根据不同摇杆指令,对四个电机的占空比进行加加减减。当时我遥控器的板子应该是画好了,我还在另外的一本书上看到了一块可以把AV信号转成RGB565的芯片,这样的话我连图传显示也可以自制了,但是最后进度卡在了姿态解算上面。卡尔曼滤波我看不懂,四元数我也看不懂,书上也没有讲清楚。当时我就是这样子的,遇到不能理解的东西就很容易做不下去,我觉得自己水平不够,看不懂那些高深的数学。不明白当时为什么没有直接调库的想法,现在想想也挺奇怪的。我甚至还问了我的研究生朋友:不加飞控可以飞吗?显然我当时只想要一架飞机,一个可以显摆的玩意。

Read More

大学的时候写下的一段SQL查询

大学的时候写下的一段SQL查询

翻手机相册的时候发现一张截图:

现在的我,对于SQL的印象就只剩下SELECT * FROM了,什么游标,子表全部忘得干干净净。不过我还记得这应该是大学数据库课程的某个作业吧,当时一直想着能不能在一条SQL语句中,实现作业的要求。那时候想了很久才想出来,很有成就感。虽然题目的要求是什么,都有哪些表,现在都记不起来了,再加上现在的自己是真的很菜,翻到这张截图的时候很是感慨,当时就很喜欢写这种一行代码,超短代码又或者是优雅代码的实现。记得还学过一个用Python的dict模拟switch语句的方法:

1
2
3
4
5
{
"a": lambda x: f1(x),
"b": lambda y: f2(y),
"c": lambda z: f3(z),
}["b"](x)

以及Python交换两个对象的方法:

1
x, y = y, x

隔了好几年再看自己的代码,确实有种很陌生的感觉。我想,找点时间,把我以前折腾过的东西都记录记录吧,虽然都是黑历史,但是也是成长史,以后回来看看也挺好的。

CPP多态与虚函数

[toc]

CPP多态与虚函数

印象中对于多态的理解是,通过父类指针调用类方法时,将根据指针指向的对象类型调用相应的类方法。今天我突然有了一个疑问,如果父类中有一个非虚函数调用了一个虚函数,并且在子类中对该虚函数进行了重写,那么通过子类对象或者基类指针调用该方法时,程序的行为会是什么样的呢?

Read More

最大子数组和

最大子数组和

就快要秋招了,又该准备刷题了。其实一直都很反感刷题这件事,大一的时候就刷OJ,找实习的时候刷LeetCode,找工作的时候也刷,考研的时候又刷一回,现在又得再刷一回。刷题这事吧,挺花时间,但是收益并不高,这几天刷题,过几天去忙点其他事,基本就忘得差不多了。很无奈,你不刷,企业就觉得你基础不行,coding不行。想想后面还得再回去看八股文,头都大了,计算机专业课,可以说也是反反复复学了好多遍吧,也是学了忘,忘了学,但是实际用上的知识,不多。

这是上个月的事情了。信软的妹妹给我发来一道题,LeetCode的第53题,最大子数组和。这个题目要求在一个给定的整数数组中,找到一个连续子区间,使得子区间中元素的和最大。

既然是妹妹发的,那肯定不能做不出来,一时间胜负欲拉满。我当时看完题目的时候,坚信用双指针能解出来。理由是,要寻找的子区间是一个连续的区间,两个指针之间也是连续的子区间,如果能够通过移动两个指针,使它们逐步向目标子数组靠近,不就可以解决了吗?

一开始是想着能不能只经过一次遍历,就能找到最大子数组和呢?先初始化左右指针,初始时刻都指向数组首元素,结合滑动窗口的思想,右指针不断右移,扩大窗口的大小,左指针也向右移动,但是不超过右指针,维护一个求和的变量,右指针每移动一次,就把指向的元素加进来,左指针每移动一次,就把指向的元素减去,这样,求和变量就能记录窗口中元素的和,只需要找到目标窗口就可以了,也就是什么时候右指针该移动,什么时候左指针该移动的事了。

Read More

不规则平面区域的渐变过渡算法

[toc]

一、问题描述

这是个两年前的工作了,想着如果不整理一下,哪天电脑坏了,估计也就跟着没了吧,这样的事情也不少发生。

当时在设计一个新算法,其中的一小步就是需要对不规则平面区域进行插值。不规则平面区域由封闭曲线构成,下图给出了一个例子:

当然,上面这张图片中的云朵形状还是过于复杂了,但是暂时没找到合适的示意图,就凑合吧。实际需求没有这么复杂,形状整体上更偏向于一个凸集。

这里要解决的问题是,对于由封闭曲线构成的不规则区域,如何设计一个类似双线性插值的算法,使得区域内部的点能够根据区域轮廓曲线的属性值,从上至下或者从左至右进行平滑过渡呢?

Read More

一个关于实例分割的idea

[toc]

一、开篇矫情一下

2020年的时候有过一个关于实例分割的想法,一开始还想着做实验验证一下这个想法是否可行,但是自己没有服务器,兜里也没几个钱可以租服务器了,一个人孤军奋战,每一步都走得挺艰难的,而且觉得自己像是个民科,慢慢地就没了热情,后来也就不了了之。

读研后偶尔也会想起这个事,我想,还是记录一下吧,当作回忆或者分享都可以。

二、Yet-Another Curve GCN (YACG)

2.1 算法Overview

整个算法的pipeline可拆分成如下部分:

  1. 物体边缘的角点(拐点)检测;
  2. 基于角点检测结果,提取角点坐标信息和角点处特征信息,构建节点向量;
  3. 以某种策略(如k最近邻)连接节点,构建出一个图;
  4. 应用图卷积网络,预测节点的精确位置,节点之间的边是否连接以及边的属性值(如曲线的参数);
  5. 应用图遍历算法,得到单个实例;
  6. 应用图卷积网络,构建更高层语义信息。

Read More

一个有趣的最优化选课问题

UESTCourse

电子科大学生排课脚本代码

一、简介

​ UESTCer在选择了自己心仪的课程之后,往往需要根据自己的时间安排进行排课。在排课的时候,大多数课程都会有多个开班,将自己所选课程加入自己的课程表中并且不会发生冲突,同时又能保证特定时间段可以空闲出来(如:开组会),有时是件枯燥且烦恼的事情(如:想要的排课方案压根不存在)。

​ 为了解决这个问题,该排课脚本应运而生。该排课脚本使用Python语言进行编写,能够快速且高效地生成所有可行的排课方案,同时允许设置时间占位符以及选择校区,并最终以课表形式保存为MarkDown文档,方便查看。排课算法使用回溯法,采用递归实现,代码整体结构清晰整洁。

二、使用方式

注意:如果你的计算机上没有Python,可以在Python官网下载安装。

  1. 将代码下载到本地:

    1
    2
    # 在命令提示符中输入
    git clone https://github.com/mo-vic/UESTCourse.git
  2. 安装代码依赖:

    1
    2
    # 在命令提示符中输入
    pip3 install -r requirements.txt
  3. 从个人网上选课系统的选课页面复制课程信息,粘贴到一个新建的Excel文件里面,Excel表格头格式为:

    课程编号 课程名称(班级) 开课院系 任课教师 上课时间地点 校区 学时 学分 容纳人数 预选人数

    注意Excel文件中只保留自己想选的课程!!!

  4. UESTCourse文件夹目录下,打开命令提示符,运行如下命令:

    1
    python3 start.py --campus="清水河" --time_placeholder="星期三第5-6节" --time_placeholder="星期三第7-8节" --excel "Courses.xlsx"

    其中:

    --campus:指的是校区,后面的参数可以是"清水河""沙河",若不指定--campus参数,则默认为两个校区。

    --time_placeholder:指的是时间占位符,可以设置空闲时间(如:组会时间)。设置格式示例:星期三第5-6节

    --excel:上述课程信息Excel文件的所在路径。

  5. 查看在UESTCourse文件夹目录下生成的Schedule.md,推荐使用TyporaVisual Studio Code打开。

三、最优化选课

如何在所有心仪的课程中,找到一个时间不冲突的排课方案,使得课程总学分最高呢?

设每个课程是否选择为,对应的学分为,总学分,对于时间冲突的课程,有约束,则该排课问题的数学模型为整数规划:

四、To Do

  • 优化时间冲突检测
  • 打包成可执行文件