第一部分:
1.<< 和 >> 符号可比喻成“数据流的动向”,如“流向哪里”
2.C++的文件操作
3.
#include <iostream>
#include<string>
using namespace std;
int main()
{
string myString;
cout << "请输入一串字符:";
getline(cin, myString);
cout << "输入的字符串为:" << myString << endl;
return 0;
}
4.对齐。如32位的程序对齐是按照四个字节来对齐,1个字节等于8位。方便CPU的处理。
5.寻址
6.特别说明:要实现真正的“速度”,例如,这就要求系统是64位的,程序是64位的,CPU是64位的,这样才吻合
7.用&取不到字符数组的地址,却能取到整形数组的地址。(那段内存当字符串使用呗,遇到/0结束输出。cout重载的问题。所有指针,都按指针形式输出,char *做了特化,按照字符串输出…cout << "hello"其实就是被当作const char*类型做字符串输出了。把它强转成int*,void*,各种指针就可以了。)
8.指针注意小细节
既然普通变量也可以存储地址,那为什么还要用指针变量呢?
比如 像
1) int a,b;
a=&b;
2) int b,* a;
a=&b;
既然都可以干嘛要用呢?
答:不可以这样用。貌似没有任何问题,其实不然。当1)中的a加1时,就会出现问题。如果a是一个整型变量,赋值表达式a=a+1,表示a所对应的内存地址的值加1后所得的数再存入a所对应的地址,亦即b的地址加1。此时a指向赋值后的地址,亦既&b+1的地址(b之后的第一个字节)。如果这样用,有时可能会导致无法完全读出字节中的数据,因为某些数据可能要在连续的内存中存储。而上面所说的a如果加1再加1后,只能在一个字节上存储,这样就导致有些数据无法存储或读出;如果a是一个指针变量,并指向整型变量时,a=a+1表示a越过2个字节(a是整型变量,占2个字节),指向后面的第3个字节,它里面的值是未知的,但是指针a已不再指向原来的地址,而指向a后面的第3个字节。这样用,可以保证无论对a加或减,都可以保证读出或写入完整的数据(如果有的话)。2)和1)是同样的道理。
9.指针和数组
10.结构体与指针
11.继承的访问控制
12.友元关系(类中的属性和函数或者子类无直接联系,但是函数或子类需要访问类中的属性,这是声明下友元关
系是一种体现)
13.C++内存分配方式概述
14.把父类的方法定义为虚函数,可以让子类继承并覆盖父类方法时,然后“父类声明,子类实现”时的方法会正
常覆盖父类方法,而不是因为编译器找最优的实现而继续调用父类的方法。
虚方法 --> 抽象方法 --> 多态性(一个接口,多种方法)
15.运算符重载
16.虚继承
17.避免运行时错误经验
18.动态内存
第二部分:
1、每个对象在创建时都会自动调用该类的构造函数,试想下,如果构造函数能返回值,但是也无法接收啊,因为创建对象是:类名 对象名; 此时构造函数就自动调用了,有返回值的话怎么将返回值赋值给变量,析构函数没有返回值也同理
2、堆是采用匿名的方式来保存数据的,你只能通过指针来访问这些数据
3、指针可以存放在栈中,较大的数据放在堆中,指针存放堆中数据的地址,nice,栈的速度比堆快,这样也可以减少在堆中产生碎片。注意堆内存由程序员申请和释放,相当于生命周期由程序员控制。但是保存给堆数据地址的指针,却是局部变量,当指针被系统释放后,就没有人知道堆内存数据去哪里找了,导致内存泄露
4、delete关键字将释放指针锁指向的内存,如delete p ,而不会释放指针,所以可以继续使用指针。注意,不能进行两次delete p,因为第一次已经释放了指针指向的内存了,再次删除会崩溃
5、构造函数和类名一致,析构函数在类对象销毁时才会自动执行
6、要分清楚存储在栈中的对象和堆中的对象的区别:
栈中的对象(非new),出了函数作用域就会自动调用析构函数,从而释放掉;
堆中的对象(new出来的),需要程序员主动去释放,不然直到程序结束才会释放
7、this指针的创建和删除由编译器完成,程序员不必操心
8、开辟堆内存空间 p1,delete p1;然后又开辟p2,注意!这时的p2其实指向的是p1,因为p1被释放后又被利用起来了
9、const指针,即常量指针它自身的值是不可改变的,但指向的值可以改变
10、注意函数传参的“按值传递”、“按址传递”、“按别名传递”的区别
11、用已有对象来创建对象时,才会调用复制构造函数;用已有对象来赋值已有对象时,会调用赋值运算符函数
12、只要创建一个类,编译器就会自动添加一下4个函数:
默认构造函数
析构函数
默认复制构造函数
默认赋值运算符函数
13、异常处理接住(catch)抛出来的异常后,可以不处理,继续往外抛(throw);throw and catch使得一些代码被“忽视”,从而不被执行
14、throw可以抛出任何东西,然后catch接收
15、STL六大组件:容器(container)、算法(algorithm)、迭代器(iterator)、仿函数(function object)、适配器(adaptor)、空间配制器(allocator)
16、在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>、<utility>
第三部分:
1. system函数后面的系统进程命令执行语句有同步和异步区分。比如直接的系统命令必须要等待当前程序退出才会继续执行,所以应该采用异步命令形式。
2.算法的特点
3.#define才是真正意义上的常亮,而const声明的变量可以间接修改其值,通过指针获得变量存储地址进行修改即可。C语言可以改变变量的值,而汇编是可以连寄存器的值都可以改变的语言。
4.数据交换万能公式。
a = a + b a = a * b
b = a – b b = a / b
a = a – b a = a / b
a = a ^ b
b = a ^ b
a = a ^ b
(异或是位运算中比较安全的计算)
4.平时运行代码是DOS模式,所以会出现DOS窗口。以下是windows模式。
5.dll导出接口供外部程序使用
6.注意,编译的意义是“呼叫实体,即编译成功不一定执行成功,因为呼叫实体(函数等)并不一定要求实体已创建好”,例如,我打电话给警察叔叔是可以的(编译),但是警察叔叔是实体,来不来(运行、执行)是一回事。
6.#include头文件的时候,前提是路径下要事先有生成 .lib文件。
7.有时候在企业,可能只要你写写模块(.dll)或者写写库(.lib)。
8.函数执行流程
9.函数笔记
10.寄存器变量
11. 一个进程不可以随便直接读写另外一个进程的内存,所以,有时候需要通过模块来对进程进行注射,即dll注射。