——————/第5章 基本概念
x=(y==z) //相等返回布尔值1,否则0
printf(“”,*ptr,*(ptr++)); //从右到左计算
——/
float a=0.0f;
结果:0 0x22fe4c 0
cout<<boolalpha<<( (int)a==((int&)a )<<endl; //以true、false形式输出
——/
unsigned int a=0xfffffff7;
char*b=(char*)&a;
printf("%x",*b);
结果fffffff7,等价:
unsigned int *p=&a;
char*b=(char*)p;
为char型指针转换,非char型转换,仅影响指针寻址
——/
判断x是否为2的n次方(2、4、8、…)
因10、100、1000,故!(x&(x-1))
——————/第6章 预处理、const和sizeof
宏FIND求结构体struct里某个变量的偏移量:
#define FIND(struct,e) (size_t)&(((struct*)0)->e)
——/
c++ const定义类中某成员函数为恒态函数,即不改变类中数据成员
IDE可对const常量进行调试,但不能对宏常量进行调试
c++中const常量可完全取代宏常量
用mutable修饰成员变量后,即可在const成员函数中更改之
char q[]=”abc”; //sizeof(q)=4
——/
当结构体内元素长度都小于处理器位数,则以结构体内最长数据元素为对齐单位
…………………………….....大于等于…………….,以处理器位数为对齐单位
bool int bool占12字节 int bool bool占8字节
——/
——/
class A{};class B{}; //1
class C:public A{}; //1
class D:public virtual A{}; //32位系统4,因涉及虚指针
class E:public A,public B{}; //1
——/
——/
sizeof关键字
括号中内容不被编译,被类型替代,如sizeof(a=5)->sizeof(int),a值未变
编译阶段被函数返回值类型替代sizeof(f())->sizeof(int)
sizeof(string); //4
——/
string arr[]={"lyl","lm","lcy"};
sizeof(arr)/sizeof(string); //正确,结果3
string * str=new string[2];
str[0]="lk";
str[1]="gzz";
sizeof(str)/sizeof(string); //错误,因sizeof(str)指针为4,改为:
sizeof(*str)*2/sizeof(string);
——————/第7章 指针和引用
常量定义时需同时初始化
字符串常量保存于只读数据段,全局变量保存于普通数据段(静态存储区)
B*p=(B*)&a;
p->funx(); //1
当p->funx()打印c,编译器对c认识是距对象首偏移0,于是打印对象a首开始int变量值
——/
char*c[]={“lyl”,”lcy”,”jxc”};
char**p=c;
p++;
cout<<*p<<endl; //lcy
——/
delete后p为迷途指针,非空指针两次delete导致程序崩溃,但delete空指针则很安全
句柄与指针为截然不同概念,句柄作用标记系统资源,为32bit的uint,指针为内存地址
——————/第10章 面向对象
静态数据成员必须只能在类体外进行初始化
静态私有成员可通过静态公有函数访问
常量必须在构造函数初始化列表里初始化或设置为static后直接初始化,如:
const int v;
A(int i):v(i){}
——/为何virtual析构函数是必要的?
Base*p=(Base*)&c;
delete p;
不将~Base()定义为virtual函数,仅打印~Base,导致内存未完全释放,定义为virtual后:
~Child ~Base //子类析构调用父类析构
——/
不能声明每个函数为虚函数,因产生额外系统开销
析构函数可以为内联函数
友元函数非类的函数
——/String类的构造、析构、拷贝函数
cout<<c.getdata()<<endl;
1
A getdata
B dogetdata
cout<<c.A::getdata()<<endl; //同上
cout<<c.B::getdata()<<endl; //同上
cout<<c.C::getdata()<<endl; //同上
cout<<c.dogetdata()<<endl;
1
B dogetdata
cout<<c.A::dogetdata()<<endl;
0
A dogetdata
cout<<c.B::dogetdata()<<endl;
1
B dogetdata
cout<<c.C::dogetdata()<<endl; //同上
就进调用,父辈存在则优先调用,否则调用祖父辈
——/
pa->f();
B*pb=(B*)pa;
pb->f();
A中为虚,输出AA,否则AB
——/
c++ protected成员类外无法访问,子类可访问
多重继承有利于代码复用,但易引起二义性(多个基类含同名成员)
包含非纯虚函数可定义对象,纯虚否
每一对象都有一虚指针指向该类虚函数表
避免某类被实例化:①抽象类②构造函数声明为private
何时编译器默认生成拷贝构造函数:你没提供而程序又需要
RTTI: (Run Time Type Identification鉴定、识别)
——/
class B: virtual public A
class C: virtual public B
大小分别为:8 16 24(虚继承实现为加入虚类指针指向父类)
——/
虚继承:
class A;
class B:virtual public A;
class C:virtual public A;
class D:public B,public C;
——/
B*pb=dynamic_cast<B*>(pc);
A*pa=dynamic_cast<A*>(pc);
if(pb==pc)
cout<<"equal"<<endl; //省略else分支
if((int)pc==(int)pb)
cout<<"equal"<<endl;
结果:equal、notequal
因pb==pc两端数据类型不同,比较时需进行隐式类型转换,相当于(C*)pb==pc(pb实际指向对象c中子类b部分,隐式类型转换后同)
——/
class Derive:Base //不指定默认private继承
struct a
{
int x:1;
int z:3;
};
占4字节,int z:33错误,超4字节,内存越界
——/
static_cast:基本类型间转换
reinterpret_cast:指针类型间转换,直接复制二进制位
const_cast:去除变量const属性
dynamic_cast:主要用于类层次间转换
——/
unsigned char s=0;
s=s-1; //1111 1111
pc机内存数据低位存低地址
——————/第13章 数据结构基础
调函数时先进行参数压栈,顺序从右到左(window平台,栈从上向下生长)
归并排序稳定
int a[n],n=10报错n未定义,int n=10,a[n]正确
——/
heap堆与stack栈区别:
①stack由os自动分配释放,heap手动分配释放
②stack空间有限
③分配方式不同
——/冒泡排序
作业:用户在一次事务处理过程中要求计算机所做工作的集合
window编程中互斥器mutex(进程间互斥)和临界区critical section(线程间互斥)类似
死锁是指两个或两个以上进程在执行过程中,因资源争夺而造成互相等待的现象,若无外力作用,它们都将无法推进下去:互斥条件、请求与保存、循环等待、不可剥夺
——/
进程与线程区别:
①进程是程序的一次执行,进程间是独立的,表现在内存空间、上下文环境,线程运行在进程空间内
②进程无法突破进程边界访问其它进程空间,线程由于处于进程空间内,故同一进程所产生线程共享进程内存空间
③同一进程内两段代码不能同时执行,除非引入线程
④线程属于进程,当进程退出时该进程所产生的线程都会被强制退出
⑤线程占用的资源少于进程占用的资源,进程与线程都可以有优先级
——/
dll调用方式:①静态调用②动态调用
垃圾回收机制:不再考虑内存管理,有效防止内存泄露(对堆内存中已经死亡或长时间不用的对象进行清除与回收),使对象无作用域概念,只有对象的引用才有作用域
x=(y==z) //相等返回布尔值1,否则0
printf(“”,*ptr,*(ptr++)); //从右到左计算
——/
float a=1.0f;
cout<<(int)a<<endl;
cout<<&a<<endl;
cout<<(int&)a<<endl; //以int形式解读float内存
结果:1 0x22fe4c 1065353216
float a=0.0f;
结果:0 0x22fe4c 0
cout<<boolalpha<<( (int)a==((int&)a )<<endl; //以true、false形式输出
——/
unsigned int a=0xfffffff7;
char*b=(char*)&a;
printf("%x",*b);
结果fffffff7,等价:
unsigned int *p=&a;
char*b=(char*)p;
为char型指针转换,非char型转换,仅影响指针寻址
——/
判断x是否为2的n次方(2、4、8、…)
因10、100、1000,故!(x&(x-1))
——————/第6章 预处理、const和sizeof
宏FIND求结构体struct里某个变量的偏移量:
#define FIND(struct,e) (size_t)&(((struct*)0)->e)
——/
c++ const定义类中某成员函数为恒态函数,即不改变类中数据成员
IDE可对const常量进行调试,但不能对宏常量进行调试
c++中const常量可完全取代宏常量
用mutable修饰成员变量后,即可在const成员函数中更改之
char q[]=”abc”; //sizeof(q)=4
——/
struct {
short s1,s2,s3;
}A;
struct {
long l; short s;
}B;
A占6字节,B占8字节
当结构体内元素长度都小于处理器位数,则以结构体内最长数据元素为对齐单位
…………………………….....大于等于…………….,以处理器位数为对齐单位
bool int bool占12字节 int bool bool占8字节
——/
class A
{
int a;
static int b;
};
4字节,因sizeof计算栈中分配内存大小
——/
class A{};class B{}; //1
class C:public A{}; //1
class D:public virtual A{}; //32位系统4,因涉及虚指针
class E:public A,public B{}; //1
——/
class Base
{
public:
Base(){}
~Base(){}
virtual void f(int){}
virtual void f(double){}
virtual void g(int i=10){}
void h(int i=10){}
};
大小4,因仅包含指向虚函数表指针
——/
sizeof关键字
括号中内容不被编译,被类型替代,如sizeof(a=5)->sizeof(int),a值未变
编译阶段被函数返回值类型替代sizeof(f())->sizeof(int)
sizeof(string); //4
——/
string arr[]={"lyl","lm","lcy"};
sizeof(arr)/sizeof(string); //正确,结果3
string * str=new string[2];
str[0]="lk";
str[1]="gzz";
sizeof(str)/sizeof(string); //错误,因sizeof(str)指针为4,改为:
sizeof(*str)*2/sizeof(string);
——————/第7章 指针和引用
常量定义时需同时初始化
字符串常量保存于只读数据段,全局变量保存于普通数据段(静态存储区)
class A
{
public:
A()
{
a=1;b=2;
}
void fun()
{
cout<<a<<b<<endl;
}
private:
int a,b;
};
class B
{
public:
B()
{
c=3;
}
void funx()
{
cout<<c<<endl;
}
private:
int c;
};
A a;
B*p=(B*)&a;
p->funx(); //1
当p->funx()打印c,编译器对c认识是距对象首偏移0,于是打印对象a首开始int变量值
——/
char*c[]={“lyl”,”lcy”,”jxc”};
char**p=c;
p++;
cout<<*p<<endl; //lcy
——/
delete后p为迷途指针,非空指针两次delete导致程序崩溃,但delete空指针则很安全
句柄与指针为截然不同概念,句柄作用标记系统资源,为32bit的uint,指针为内存地址
——————/第10章 面向对象
静态数据成员必须只能在类体外进行初始化
静态私有成员可通过静态公有函数访问
常量必须在构造函数初始化列表里初始化或设置为static后直接初始化,如:
const int v;
A(int i):v(i){}
——/为何virtual析构函数是必要的?
class Base
{
public:
~Base()
{
cout<<"~Base"<<endl;
}
};
class Child:public Base
{
public:
~Child()
{
cout<<"~Child"<<endl;
}
};
Child c;
Base*p=(Base*)&c;
delete p;
不将~Base()定义为virtual函数,仅打印~Base,导致内存未完全释放,定义为virtual后:
~Child ~Base //子类析构调用父类析构
——/
不能声明每个函数为虚函数,因产生额外系统开销
析构函数可以为内联函数
友元函数非类的函数
class Base
{
public:
explicit Base(int i)
{
cout<<"Base(int i)"<<endl;
}
};
Base b=1; //加explicit(防止隐式类型转换)后,该行编译出错
——/String类的构造、析构、拷贝函数
class String
{
private:
char*m_str;
public:
String(const char*str=NULL)
{
if(str==NULL)
{
m_str=new char[1];
*m_str='\0';
}
else
{
int length=strlen(str);
m_str=new char[length+1];
strcpy(m_str,str); //拷贝包含NULL
}
}
~String()
{
delete [] m_str;
}
String(const String&other)
{
int length=strlen(other.m_str);
m_str=new char[length+1];
strcpy(m_str,other.m_str);
}
};
——————/第11章 继承与接口
class A //省略构造函数及封装关键字
{
int data; //0
int getdata()
{
return dogetdata();
}
virtual int dogetdata()
{
return data;
}
};
class B:public A
{
int data; //1
int dogetdata()
{
return data;
}
};
class C:public B
{
int data; //2
};
C c(10);
cout<<c.getdata()<<endl;
1
A getdata
B dogetdata
cout<<c.A::getdata()<<endl; //同上
cout<<c.B::getdata()<<endl; //同上
cout<<c.C::getdata()<<endl; //同上
cout<<c.dogetdata()<<endl;
1
B dogetdata
cout<<c.A::dogetdata()<<endl;
0
A dogetdata
cout<<c.B::dogetdata()<<endl;
1
B dogetdata
cout<<c.C::dogetdata()<<endl; //同上
就进调用,父辈存在则优先调用,否则调用祖父辈
——/
class A
{
public:
virtual void f()
{
cout<<"A"<<endl;
}
};
class B:public A
{
public:
void f()
{
cout<<"B"<<endl;
}
};
A*pa=new A();
pa->f();
B*pb=(B*)pa;
pb->f();
A中为虚,输出AA,否则AB
——/
c++ protected成员类外无法访问,子类可访问
多重继承有利于代码复用,但易引起二义性(多个基类含同名成员)
包含非纯虚函数可定义对象,纯虚否
每一对象都有一虚指针指向该类虚函数表
避免某类被实例化:①抽象类②构造函数声明为private
何时编译器默认生成拷贝构造函数:你没提供而程序又需要
RTTI: (Run Time Type Identification鉴定、识别)
class A
{
char a[3];
};
class B:public A
{
char b[3];
};
class C:public B
{
char c[3];
};
sizeof(A) sizeof(B) sizeof(C) //3 6 9
——/
class A
{
char a[3];
virtual void aa(){}
};
class B: public A
{
char b[3];
virtual void bb(){} //
};
class C: public B
{
char c[3];
virtual void cc(){}
};
大小分别为:8 12 16
class B: virtual public A
class C: virtual public B
大小分别为:8 16 24(虚继承实现为加入虚类指针指向父类)
——/
虚继承:
class A;
class B:virtual public A;
class C:virtual public A;
class D:public B,public C;
——/
class A
{
int a;
};
class B
{
int b;
};
class C: public A,public B
{
int c;
};
C*pc=new C;
B*pb=dynamic_cast<B*>(pc);
A*pa=dynamic_cast<A*>(pc);
if(pb==pc)
cout<<"equal"<<endl; //省略else分支
if((int)pc==(int)pb)
cout<<"equal"<<endl;
结果:equal、notequal
因pb==pc两端数据类型不同,比较时需进行隐式类型转换,相当于(C*)pb==pc(pb实际指向对象c中子类b部分,隐式类型转换后同)
——/
class Derive:Base //不指定默认private继承
class Base
{
protected:
int i;
public:
Base(int x){i=x;}
};
class Derive:public Base
{
private:
int i;
public:
Derive(int x,int y):Base(x) //必须如此
{
i=y;
}
int print(){...}
};
——————/第12章 位运算与嵌入式编程
struct a
{
int x:1;
int z:3;
};
占4字节,int z:33错误,超4字节,内存越界
——/
static_cast:基本类型间转换
reinterpret_cast:指针类型间转换,直接复制二进制位
const_cast:去除变量const属性
dynamic_cast:主要用于类层次间转换
——/
unsigned char s=0;
s=s-1; //1111 1111
pc机内存数据低位存低地址
——————/第13章 数据结构基础
调函数时先进行参数压栈,顺序从右到左(window平台,栈从上向下生长)
归并排序稳定
int a[n],n=10报错n未定义,int n=10,a[n]正确
——/
heap堆与stack栈区别:
①stack由os自动分配释放,heap手动分配释放
②stack空间有限
③分配方式不同
——/冒泡排序
void maopao(int*list) //时间复杂度很差O(n^2)
{
int i,j,temp;
for(i=0;i<9;i++)
for(j=0;j<9-i;j++)
{
if(list[j]>list[j+1])
{
temp=list[j];
list[j]=list[j+1];
list[j+1]=temp;
}
}
}
int main()
{
int i;
int list[10]={5,7,4,1,3,2,6,9,8,0};
maopao(list);
for(i=0;i<10;i++)
cout<<list[i]<<endl;
return 0;
}
——————/第16章 操作系统
作业:用户在一次事务处理过程中要求计算机所做工作的集合
window编程中互斥器mutex(进程间互斥)和临界区critical section(线程间互斥)类似
死锁是指两个或两个以上进程在执行过程中,因资源争夺而造成互相等待的现象,若无外力作用,它们都将无法推进下去:互斥条件、请求与保存、循环等待、不可剥夺
——/
进程与线程区别:
①进程是程序的一次执行,进程间是独立的,表现在内存空间、上下文环境,线程运行在进程空间内
②进程无法突破进程边界访问其它进程空间,线程由于处于进程空间内,故同一进程所产生线程共享进程内存空间
③同一进程内两段代码不能同时执行,除非引入线程
④线程属于进程,当进程退出时该进程所产生的线程都会被强制退出
⑤线程占用的资源少于进程占用的资源,进程与线程都可以有优先级
——/
dll调用方式:①静态调用②动态调用
垃圾回收机制:不再考虑内存管理,有效防止内存泄露(对堆内存中已经死亡或长时间不用的对象进行清除与回收),使对象无作用域概念,只有对象的引用才有作用域