(一)在第一周的学习中,我们首先学习了递归算法,对递归的要求并不算太高,主要是温习一下之前学过的知识,并且在 算法设计与分析 这门课中,会比较的轻松:
递归:
递归的关键在于找出递归定义和递归终止条件。
递归成功的秘诀在于:
我们不用担心递归方法是如何解决子问题的。
只要简单地了解它能正确地解决子问题,而且使用子问题的求解结果就能正确地解决原问题。层层递归,最终便可得到最终的答案。
记忆化搜索:
在递归的过程中,将已经计算出来的结果保存起来,当之后的计算用到的时候直接取出结果,避免重复运算,因此极大的提高了算法的效率,也就是空间换时间。
我们在一般情况下,主要是使用数组。
(二)在第二周的学习中,我们学习了结构体以及指针和引用的相关知识。结构体的内容,在学到类之后,就差不多被类所代替了,因为类有比较好的封装性:
结构体引用成员的三种等价形式:
① 结构体变量.成员名
②(*结构体指针变量名).成员名 (注意括号)
③ 结构体指针变量名->成员名
指针及引用:
new运算符:
-
分配单个对象:new 类型 或者 new 类型(初始值)
int* ip1 = new int; int* ip2 = new int(100);
-
分配多个连续存储的对象:new 类型[数组大小]
int* ipa = new int[100];
-
定位new,在指定位置分配空间:new (指针) 类型;
delete运算符:
- 释放new分配的空间
delete 指针;
delete[] 指针;
const限定指针:
(1)指向const对象的指针(非const ):
const type *cp; //或者type const *cp;
cp是指向常量的指针,它所指向的内存中的内容不可以改变,即*cp的值不能改变
(2)指向非const对象的const指针:
type* const cp = initAddressValue;
cp是常量指针,初始化后值不能改变,指向固定的单元
(3)指向const对象的const指针:
const type* const cp = initAddressValue;
const int ival = 5;
const int* const pi = &ival;
//pi是一个指向const对象的const指针
引用:
一般在程序中,引用主要用作函数的参数。
必须被初始化,初始值是一个有内存地址的对象。
使用左值引用时注意:
- 引用并非对象,是为已存在的对象所起的另一个名字
- 引用只能绑定到对象(有内存地址)上,不能与字面值或某个表达式的计算结果绑定在一起。
有空指针:
指针可以不指向任何对象,其值为0,表示空指针
没有空引用:
引用必须指向一个对象,而且一直指向该对象,不存在“空”引用。
(三)在第三周的学习中,我们学习了类的使用(包含一些特殊的函数),当然也学会了使用C++的特色之一 —— 初始化列表:
类的使用:
数据成员:
- 除了静态 static 数据成员外,数据成员不能在类体中被显式地初始化
- 类的成员可以是其他类的对象,称为类的组合。但不能以类自身的对象作为本类的成员。
成员函数:
利用构造函数创建对象:
类名 对象名[(实参表)];
类名 *指针变量 = new 类名[(实参表)];
构造函数初始化成员有两种方法:
- 使用构造函数的函数体进行初始化
- 使用构造函数的初始化列表进行初始化
析构函数:
- 析构函数自动调用(隐式调用)
- 析构函数没有返回值,不能有参数,也不能重载
如果没有定义任何构造函数 ,C++编译器会自动创建一个默认构造函数 。 如果已经定义了一个构造函数,编译器不会自动创建默认构造函数,只能显式调用该构造函数。
何时使用初始化列表:
- 常量成员
- 引用类型
- 没有默认构造函数的类类型
初始化列表的注意点:
1 因为初始化列表中无法直接初始化基类的数据成员,所以我们需要在列表中指定基类的构造函数,如果不指定,编译器则会调用基类的默认构造函数。
2 推荐使用初始化列表,它会比在函数体内初始化派生类成员更快,因为在分配内存后,在函数体内又多进行了一次赋值操作。
3 初始化列表并不能指定初始化的顺序,正确的顺序是,首先初始化基类,其次根据派生类成员声明次序依次初始化,因此,我们现在最好就养成良好的顺序习惯。
(四)在第四周的学习中,我们主要学习了this指针、复制构造函数、浅复制、深复制的相关内容:
this指针的使用:
- 在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;
- 当参数与成员变量名相同时,如this->n = n (不能写成n = n)。
复制构造函数:
语法形式:
类名 :: 类名(const 类名 & 引用名 , …);
复制构造函数的特点:
- 复制构造函数名与类名相同,并且也没有返回值类型。
- 复制构造函数可写在类中,也可以写在类外。
- 复制构造函数要求有一个类类型的引用参数。
- 如果没有显式定义复制构造函数,系统自动生成一个默认形式的复制构造函数。
复制构造函数的调用 :
-
声明语句中用类的一个已知对象初始化该类的另一个对象时。
Point ob1; Point ob2(ob1);
但是:下面的因为s2已提前声明,所以不会调用复制构造函数:
Point ob1; Point ob2; ob2=ob1;
-
当对象作为一个函数实参传递给函数的形参时,需要将实参对象去初始化形参对象时,需要调用复制构造函数。
fun(Point ob1);
-
当对象是函数的返回值时,由于需要生成一个临时对象作为函数返回结果,系统需要将临时对象的值初始化另一个对象,需要调用复制构造函数。
Point fun() { Point ob2(2,6); return ob2; }
关于深复制:
● 通过一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源的复制方式称为深复制。
● 自定义复制构造函数所进行的复制是浅复制。
深复制构造函数必须显式定义
深复制构造函数的特点:
- 定义:类名::类名([const] 类名 &对象名);
- 成员变量的处理:对复杂类型的成员变量,使用new操作符进行空间的申请,然后进行相关的复制操作
(五)在第五周的学习中,我们学习了静态成员函数和友元函数,学习友元函数只是为了后面的重载,因为友元函数会破坏类的封装性:
静态成员:
- 类成员冠以static声明时,称为静态成员。
- 静态数据成员为同类对象共享。
- 静态成员函数与静态数据成员协同操作。
静态成员不属于某一个单独的对象,而是为类的所有对象所共有
class A
{
int n;
static int s;
};
定义静态成员函数的格式如下:
static 返回类型 静态成员函数名(参数表);
公有访问权限的静态成员,访问形式如下:
- 类名::静态成员函数名(实参表)
- 对象. 静态成员函数名(实参表)
- 对象指针->静态成员函数名(实参表)
- 在静态成员函数内部,直接访问。
在类外进行静态数据成员的声明:
类型 类名::静态数据成员[=初始化值]; //必须进行声明
对于类的普通数据成员,每一个对象都各自拥有一个副本。(分配不同的存储空间)
不能在成员初始化列表中进行初始化
静态成员函数没有this指针,只能对静态数据操作
(六)在第六周的学习中,我们学习了运算符重载,因为在我们自己定义的数据类型中,C++所提供的运算符难以满足我们的需求,这就需要我们来重载运算符,以达到我们需要的结果:
运算符重载规则:
- 不能重载的算符
. :: .* ?: sizeof
- 不改变运算符的优先级
- 不改变运算符的结合性
- 不改变运算符所需要的操作数
- 不能创建新的运算符
几个特殊的运算符:
赋值运算符、[] 和 () 只能用成员函数重载,不能用友元函数重载
重载流插入和流提取运算符,只能被重载成友元函数 ,不能重载成成员函数
成员函数重载:
成员运算符函数的原型在类的内部声明格式如下:
class X {
//…
返回类型 operator运算符(形参表);
//…
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
友元函数重载:
class X {
//…
friend ostream & operator 运算符(形参表);
//…
}
操作数类型不相同时,必须使用友元函数。
通过这一段时间的学习,我感受颇多:
- 首先就是学习上知识的收获,通过对程序设计B的学习,一方面,进一步加强理解了数据结构的知识,对指针的用法也进一步提高;另一方面,虽说和Java的面向对象有点区别,但是用比较的方法来学习,无疑收获会倍增。
- 对时间的把控。可能因为坚持“先苦后甜”的原则,我通常就是想赶紧完成任务,这样虽然代码交的比较早,但总有一些方面考虑的不是很周全,代码的性能也就有点低了。所以,以后还是得做好兼顾,在保证质量的前提下提高效率。
- “享受”代码。我总感觉自己的耐性不是很好,题目代码调试不出来时,总会感到急躁,看着自己的代码,就会感觉自己写的程序不叫程序。更头大的是自己看着代码,还找不出错误。自己还是太菜,仍需努力。
- 认知的提高。毕竟这是一门饭碗课,之前好像看到过,如果在IT行业不想被淘汰,平均3.5个月就得掌握一门技术。不怕别人看不起,就怕自己不争气,如果现在这门课学不好,没有一种学习方法的架构,可能以后会有好几个3.5个月才能够掌握一门技术。
- 感觉大家都很努力,也有不少的同学都比较熟练地使用STL中的知识了。当然,有句话是这么说的,你知道的越多,不知道的也就越多,然后知道的就会更多。所以,感觉还是得多多查阅相关的资料,要学的东西还会有很多很多。
- 最后,感谢老师的严格要求,这段时间过得比较充实,而又不乏乐趣,因为有代码调试成功的欣喜,感觉得自己也进步了很多。总而言之,感谢老师,感谢老师为培养您的每一位学生而努力奋斗着。
Fighting,forever!