[笔试]笔试题笔记

时间:2020-12-30 14:43:41

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)