1、32位小端模式系统下,以下程序输出为多少啊?
void main() { long long a=1; long long b=2; long long c=3; printf("%d,%d,%d\n",a,b,c); }
printf从右往左入栈,longlong是8字节长,小端系统低位放低字节,内存中存放为100000000、200000000、300000000。因此以整数4字节入栈先后0、3、0、2、0、1,最先出栈的三个为输出,分别是1、0、2.
2、拷贝构造函数、赋值函数、符号重载
一个基本的类应该包括1、构造函数 2、拷贝构造函数 3、赋值函数 4、析构函数
https://github.com/iyjhabc/study_examples/blob/master/test1.cpp
3、父类与子类的同名成员变量不会覆盖,单独存在;就近调用原则
class A//sizeof A=8 { int a; public: virtual void fun(){cout<<"i am A"<<endl;} }; class B:public A//sizeof B=12,子类与父类之间的同名变量不覆盖 { int a; public: void fun(){cout<<"i am B"<<endl;} }; class C:public B{};//sizeof C还是12,它有A::a和B::a和虚函数表 int main(){ C c; c.fun();//调用子类没定义的虚函数,采用就近调用原则。这里就近调用B,不调用A return 0; }
4、如需使用多态,父类的析构函数应该定义为虚函数。
Derive *pd=new Derive; delete pd;//先调用Base的析构函数,再调用Derrive的,正确。 Base *pb=new Derive; delete pb;//因为Base的虚构函数不是虚函数,不能多态,此处只调用了Base的虚构,造成内存泄露。 //如果Base的析构为虚,则此时会调用Derive的析构,从而会调用父类析构。
5、联合体
联合体所有成员的偏移量都是0.它的空间最大的成员的空间(考虑内存对齐后)。其实联合体里面只是单纯地存放了一个二进制数据,只是调用的时候可以根据不同的成员类型而作为不同的类型使用。
6、内存的存放区域
内存5大区域:堆、栈、常量、全局、代码
函数中const 变量还是存放在栈区,而不是常量区。堆去内存地址向上生长,栈区向下生长。
int a=3; const int b=4; cout<<&a<<" "<<&b<<endl;//0x22ff4c 0x22ff48
从下面实验证明,char *p="abc"这种初始化方式,p指向的是常量区。而且内容一样的常量会共享同一段内存。因此指向常量区的指针必须声明为const,否则修改常量区会造成崩溃。
const char *p="abc"; const char *q="abc"; cout<<(int*)p<<" "<<(int*)q<<endl;//0x46c046 0x46c046 cout<<(int*)"abc"<<endl;//0x46c046
7、不要对数组使用多态
http://coolshell.cn/articles/9543.html
Base *p=new Derived[5]; delete []p;
当sizeof(Base)==sizeof(Derived)时,可正常调用所有数组元素的虚析构函数。当子类与父类大小不同时,执行delete[]时,第一个元素的虚表能顺利找到,并执行虚析构函数。delete完第一个元素以后,系统以sizeof(Base)的偏移量跳转企图找到第二个元素的头地址,又由于子类与父类大小不等,导致找到的地址其实并不是第二个Derived元素的头地址,所以并不能正确找到其虚表,造成出错。
8、符号操作符优先级
char a=0xA5; char b=~a>>4+1;
9,从低到高位消除二进制数中的一个1
x=x&(x-1)