全是随笔,很多是看*《高质量程序设计指南C++》第三版* 的随笔。
预编译会对 预编译伪指令(一般以 # 打头,且前面只能出现空白字符)进行处理后 生成中间文件作为编译器的输入。
__LINE__ __FILE__
等分别对最小编译单元进行编译(以单个头文件所递归包含的所有文件)
运行时: 待写入
OC
-> 中间代码(.ll)
-> 汇编、机器代码
其中.ll 文件是各平台通用的。
转变命令:clang -emit-llvm -S main.m
if (aaaaaaa > bbbbbbbbbbbb)
&& (ccccccccc > ddddddddd)
&& (eeeeeeeee > fffffffff)
{
pass
}
以行为为中心
的版式(ADT/UDT)即将public成员写在前面不推荐 以数据为中心
的版式, 即将private 写在前面
C++:C++虚函数(多态确定调用哪个基类的方法)、 抽象基类(纯虚函数的基类)、 动态绑定、 运行时多态
# 虚函数表Vtable和 Vptr 一节
不要用数组来直接存放多态对象,而是存放基类指针或者基类的智能指针。 因为存放直接多态对象,会导致每次数组下标查找的是+sizeof(基类的)内存,导致第二个及以后的地址错位。
OC: 动态类型(id
)、多态绑定([obj msgSend]
)、 多态加载(图片2x3x替换,动态加方法和变量)
(*(p->_vptr[slotNum]))(p, arg-list)
; p
:基类指针, vptr
: 指p指向的对象的隐含指针, slotNum
: 调用的虚函数在vtable中的编号(编译时就确定下来的)存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:
struct stru1
{
char b; //start address is 0
short s; //start address is 2 注意这里是2 不是1(根据规则一)
int a; //start address is 0
};
虚函数表Vtable和 Vptr
一节得出vtable
总是基类先创建,然后子类拷贝再添加自己的新虚函数
virtual
函数关键字告诉编译器,派生类中相同的成员函数应该放到vtable
中去,并替换基类相应成员函数的位置;struct T
{
T(int){}; //显式创建的构造函数导致 默认构造函数不存在
string p;
};
全局对象在main之前初始化,但是顺序不确定。mian()结束后才析构。
String c= a; //调用拷贝构造,但是风格不好,应该使用 String c(a)
c = a; //赋值
void __cdecl foo(int x, int y);
默认用c++ 编译器会 产生的内部名字像 这样:__foo_int_int
的来支持函数重载 。
但是用C编译器 产生的内部名字却为:_foo
.,因为不能重载。
所以需要显式的声明 extern C
, 告诉C++编译器这是C连接函数,并指示连接器到C程序库中去找函数的定义。
const
和 非const
)virtual
可有可无。override
)指派生类成员函数遮蔽了与其同名的基类成员函数。
virtual
,都将基类函数隐藏。(不是重载)virtual
关键字,基类函数将被隐藏。(不是覆盖)例如:++a
, a++
说明:++
前置版本表示先对其执行 +1
, 然后再取值。 ++
后置版本表明先对其 取值运算,再进行+1
。
C++标准规定。当为++ / --
重载运算符时候。
++a
, 不需要带参数。Integer & operator++(){}
前置版本a++
, 需要带int参数作为标志(即哑元,非具名参数)。 Integer operator++(int){}
后置版本。inline
取代宏#define MAX(a, b) a> b ? a : b
debug
模式并没有展开,可以像普通函数一样调用,release
才真正实施内联。inine
关键字必须和实现语句放在一起,是用于实现的关键字。以下不适合用:
分别对应了STL的最基本的容器:动态数组和链接表结构
同时也代表了内存存放的两种基本方式: 连续存储和随机存储(不连续存储)
不同的存储方式决定了元素的不同访问方式:随机访问和顺序访问。
随机访问:通过恒定的开销开得到任一元素的内存地址的访问方法
顺序访问:只能从第一个元素开始进行访问
vector
支持随机访问和顺序访问list
支持顺序访问Tip
STL容器的有效元素范围,其中迭代器的last要么指向最后一个有效元素的末尾,要么指向一个空白节点,反正不是指向最后一个有效元素,其中遵循了前闭后开的原则,即[first, last)
start 到 finish 之间的是有效元素,start 到 end_of_storage 之间的是 总容量, 其中后面没有使用的控件是冗余容量,不属于容器。
多余出来的容量是未经初始化的,只是留待后续元素使用。
可以通过 capacity()
size()
查看容量和元素控件大小。
void reserve(size_type n)
是为容器请求保留的容量的大小,当现有的容器实际大小大于分配的数量的时候,vector
会在自由内存区重新分配一块更大的连续控件,其大小为现有元素的数量 n * sizeof(T)
的大小,并将所有的元素从旧位置全部复制到新的位置(调用拷贝构造函数(所以int
等基础类型都会存在拷贝构造函数等,不然放不到容器中去))。char s1[] = "";
sizeof(s1) // 1
strlen(s1) // 0
sizeof()
会加上’\0’的长度
strlen()
遇到’\0’就停止,不会加上’\0’
http://mallocfree.com/basic/c/c-6-function.htm#79