程序员面试宝典笔记

——————/第5章 基本概念
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调用方式:①静态调用②动态调用
垃圾回收机制:不再考虑内存管理,有效防止内存泄露(对堆内存中已经死亡或长时间不用的对象进行清除与回收),使对象无作用域概念,只有对象的引用才有作用域
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值