核心编程
- 内存四区分区模型
代码区:存放函数体的二进制代码,由操作系统进行管理
全局区:存放全局变量和静态变量以及常量,由操作系统释放
栈区:由编译器自动分配释放,存放函数的参数值,局部变量,形参的数据
堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
static local objects:静态对象,其生命在作用域结束之后仍然存在,直到整个程序结束。
global object:全局对象,其生命在整个程序结束之后才会消失。 - 内存四区分布
程序运行前包含:代码区、全局区。
代码区:存放CPU执行的机器指令,代码区是共享的,只读的。
全局区:全局变量、静态变量、常量区(字符串常量、其他常量例如const修饰的全局常量)
程序运行后包含:堆区、栈区。
堆区:由程序员分配释放,若程序员不释放,程序结束后由操作系统回收。主要利用new在堆区开辟内存。
int* p = new int(10);
new int[]
是新建一int型数组,数组大小在[]中指出。new int():
新建一个int型数,括号中数据初始化。
3. 引用
语法:数据类型 &别名 = 原名;
作用:给函数起别名。
引用必须初始化,初始化后就不可以更改。int &b = a;
不要返回局部变量的引用. 局部变量不可以传递、返回引用,因为局部变量在函数结束后会消失
4. 函数重载
函数重载满足条件:
1)同一个作用域下;2)函数名称相同;3)函数参数类型不同、个数不同、顺序不同。
面向对象编程
- 面向对象三大特性:封装、继承、多态(侯捷老师讲的是复合、继承、委托)
1)复合:定义:一个类里边有n个别的类 - 类名创建临时对象
类名() - 构造函数和析构函数
每个对象都会有初始设置以及对象销毁前的清理数据的设置,对象的初始化和清理是非常重要的安全问题。
构造函数的调用规则:
1)创建一个类,c++编译器会给每一个类都添加至少3个函数,即默认构造、析构函数、拷贝构造
2)如果我们写了有参构造函数,编译器不再提供默认构造,依然提供拷贝构造;
3)如果我们提供拷贝构造函数,编译器不再提供普通构造函数 - 深拷贝和浅拷贝
浅拷贝是简单的赋值拷贝;深拷贝是在堆区重新申请空间,进行拷贝操作。
如果一个类里边有指针,那么一定是需要深拷贝的。 - 构造函数的初始化列表
person(int a, int b, int c):m_A(a),m_B(b),m_C(c) {}
- 类对象作为类成员
其他类的对象作为本类的成员,构造时候先构造类对象,再构造自身。析构的顺序与构造相反。 - 静态函数static
静态成员变量:所有对象共享同一份数据;在编译阶段分配内存;类内声明,类外初始化
1)静态成员函数:所有对象共享一个函数;静态成员函数只能访问静态成员变量;静态成员函数类内声明类外实现.
2)访问方式:1.通过对象2.通过类名point::func()
3)静态成员函数是指无论创建多少个类的对象,静态成员都只有一个副本。静态成员函数即使在类对象不存在的情况下也能被调用。 - this指针
1)this指针是指向被调用的成员函数所属的对象。
2)this指针用途是:当形参和成员变量同名时,可用this指针区分;在类的非静态成员函数中返回对象本身,可使用return *this - 重载
两个自定义的数据类型相加,void operator+(){ }
左移运算符重载:可以输出自定义数据类型,最好要用全局函数重载
递增运算符重载:前置递增返回的是引用(适用于链式规则且效率较高),后置递增返回的是值。
函数调用运算符重载:由于调用起来非常像函数,被称做仿函数。 - 继承
1)继承的好处:减少重复代码
2)语法:class 子类 : 继承方式 父类
子类也称为派生类,父类也称为基类
3)继承方式有三种:公共继承、保护继承、私有继承 - 继承中构造和析构的顺序:
先构造父类,再构造子类,析构的顺序是先析构子类再析构父类。
- 多态
- 纯虚函数
1)纯虚函数语法:virtual 返回值类型 函数名 (参数列表)=0;
2)子类必须重写父类中的纯虚函数 - 虚析构和纯虚析构
1)使用条件:如果derived有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码,解决方法是将父类中的析构函数改为虚析构或者纯虚析构,如果子类中没有堆区数据就不需要写虚析构。
2)虚析构语法:virtual ~类名(){}
纯虚析构语法:virtual ~类名() = 0; 类外实现
提高编程
- 模板(泛型)
1)c++的另一种编程思想:泛型编程,主要利用的技术就是模板。
提供两种模板机制:函数模板和类模板。
语法:template - 类模板和函数模板的区别
类模板没有自动类型推导使用方式、类模板在模板参数列表中可以有默认参数 - 容器的各种形状
总的来说容器分为:序列式容器和关联式容器,各个的分类见上图。
1)array:固定元素,需要明确数组长度
2)vector:可以单向往后自动扩充,一个vector大小为12。
在内存中只能往后扩展,扩展的方式是两倍扩展。
vector.data():整个数组的起始点地址。
3)deque:双向扩充,两端可进可出,分段无序,操作可用push_back,可以用sort进行排序,但是没有qsort和bsearch因为没有首地址
4)list:双向链表,内存动态分配。有自己的sort调用自己的排序函数,不能调用全局的sort函数因为STL的sort算法迭代器不能随意跳动,是randomAccessIterator
5)forward-list:单向链表,比list占用内存更少,只能用push_front()
关联式容器:
6)set,(map包含key和value值),可以快速查找,查找非常快
set:红黑树,二分树做的,没有重复值
multiset:insert,算法find
7)map:是两个节点,包含key和value multimap<double,string >,插入元素用s.insert(pair<long,string>(i,buf));