linux c++技术面试,linux c/c++面试知识点整理(一)

1、c/c++申请动态内存

在c++中,申请动态内存是使用new和delete,这两个关键字实际上是运算符,并不是函数。

而在c中,申请动态内存则是使用malloc和free,这两个函数是c的标准库函数,使用它们必须包含stdlib.h,才能编译通过。

new/delete和malloc/free的相同之处在于,new和malloc都是手动申请动态内存,释放时new则需要delete释放内存,而malloc则需要free释放内存。

它们的不同之处在于,new和delete会自动调用对象的构造和析构函数,而malloc/free则只申请内存。

另外需要注意的是:new的不是数组的话,则直接delete就好,并且只会调用一次析构函数,而new[]的话,则需使用delete[]来释放,并且数组中每一个元素都会调用一次析构函数,调用完析构函数再释放内存。

demo如下:

#include //malloc用到

#include //memset用到

#include //printf用到

int main()

{

//malloc/free使用

int *pmalloc = (int*)malloc(sizeof(int)*4);

//注意malloc分配的内存一定要进行初始化,否则会出现一些奇怪的问题的哦

memset((void*)pmalloc, 0, sizeof(int)*4);

for(int i = 0; i < 4; i++)

{

pmalloc[i] = i;

printf("pmalloc[%d]=%d\n", i, pmalloc[i]);

}

free(pmalloc);

//new/delete使用

int *pNew = new int;

*pNew = 3;

printf("pnew = %d\n", *pNew);

delete pNew;

//new[]/delete[]使用

int *pNewEx = new int[4];

for(int i = 0; i < 4; i++)

{

pNewEx[i] = i;

printf("pNewEx[%d] = %d\n", i, pNewEx[i]);

}

//此处的[]千万不能掉,否则会导致内存泄露的

delete[] pNewEx;

return 0;

}

2、c++继承是什么以及它的优缺点

什么是继承?

顾名思义,继承是一种物体对另外一种物体某些属性,动作的接续。举个例子,比如人这个个体,它的属性包括身高,体重等这些,它的动作则包括吃饭,喝水等等,那么如果另外要定义两种物体,男人和女人,那么这些属性和动作就都可以从人这个物体中继承下来,这,就是继承。当然,继承不只是这么简单,我们后续会陆续说到的。

demo如下:

#include

class CPerson

{

public:

CPerson()

{

height = 170;

weight = 120;

}

~CPerson(){}

void DrinkWater()

{

printf("喝水\n");

}

void HavingDinner()

{

printf("吃饭\n");

}

int GetHeight()

{

return height;

}

int GetWeight()

{

return weight;

}

private:

int height;

int weight;

};

class CMan : public CPerson

{

public:

CMan(){}

~CMan(){}

};

class CWoman: public CPerson

{

public:

CWoman(){}

~CWoman(){}

};

int main()

{

CMan cMan;

cMan.DrinkWater();

cMan.HavingDinner();

printf("男人身高:%d\n", cMan.GetHeight());

printf("男人体重:%d\n", cMan.GetWeight());

CWoman cWoman;

cWoman.DrinkWater();

cWoman.HavingDinner();

printf("女人身高:%d\n", cWoman.GetHeight());

printf("女人体重:%d\n", cWoman.GetWeight());

return 0;

}

优点:类继承是在编译时刻静态定义的,且类继承可以较方便地改变父类的实现,实现函数的重用。

缺点:首先,因为继承在编译时刻就定义了,所以无法在运行时改变从父类继承的实现,其次,父类一般至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为,也就是说,如果继承下来的实现不适合子类的问题,那么父类必须重写或者被其他的类替换,这种依赖关系限制了灵活性。

从以上对比看,同一种属性既可以是优点,从另外的方面来讲,又是缺点,就看个人在编程过程中的灵活运用了。

3、c++的三大特性

封装、继承、多态。

封装是一种技术,它使类的定义和实现分离;

继承,从广义上讲,继承有三种实现方式,其一,为实现继承,指使用基类的属性和方法而无需额外编码,其二,可视继承,即子窗体使用父窗体的外观和实现代码,其三,则为接口继承,即仅仅继承属性和方法,实现则滞后到子类去实现,也就是父类使用的是纯虚函数,或者重写父类接口方法,则是虚函数,例如多态的实现就使用了接口继承。

多态,简单来讲,就是父类定义了虚函数,子类重新实现该函数,那么当父类指针指向子类时,会调用子类的该方法,这,就是多态。

下面是多态的demo:

#include

#include

class CPerson

{

public:

CPerson()

{

height = 170;

weight = 120;

memset(sex, 0, sizeof(sex));

}

~CPerson(){}

virtual void SetSex() = 0;

void PrintSex()

{

printf("我的性别是:%s\n", sex);

}

private:

int height;

int weight;

//此处sex不能是私有,否则子类中无法使用,因为子类对父类的私有成员有继承权,但没有使用权,也就是只能看,不能摸

protected:

char sex[8];

};

class CMan : public CPerson

{

public:

CMan(){}

~CMan(){}

void SetSex()

{

strncpy(sex, "男人", sizeof(sex)-1);

}

};

class CWoman: public CPerson

{

public:

CWoman(){}

~CWoman(){}

void SetSex()

{

strncpy(sex, "女人", sizeof(sex)-1);

}

};

int main()

{

CPerson* pPerson = new CMan;

pPerson->SetSex();

pPerson->PrintSex();

delete pPerson;

CPerson* pPerson0 = new CWoman;

pPerson0->SetSex();

pPerson0->PrintSex();

delete pPerson0;

return 0;

}

4、子类和父类调用构造函数和析构函数的先后顺序

子类对象定义时,先调用父类的构造函数,再调用子类的构造函数;

子类对象销毁时,如果父类析构函数是虚函数,那么先调用子类的析构函数,再调用父类的析构函数,否则只会调用父类的析构函数;

demo如下:

#include

class CPerson

{

public:

CPerson()

{

printf("建立父类\n");

}

//注意,父类析构函数一定要是虚函数,这样销毁子类时才会先调用子类的析构函数

virtual ~CPerson()

{

printf("销毁父类\n");

}

};

class CMan : public CPerson

{

public:

CMan()

{

printf("建立子类\n");

}

~CMan()

{

printf("销毁子类\n");

}

};

int main()

{

CPerson* pPerson = new CMan;

delete pPerson;

return 0;

}

执行结果如下:

建立父类

建立子类

销毁子类

销毁父类

5、什么是引用

引用,其实就是给变量取了一个别名,声明引用时要切记初始化,且引用本身不占存储单元,纯粹就是变量多了一个名称而已。

demo如下:

#include

void setValue(int & p_iValue)

{

p_iValue = 10;

}

void setValue1(int p_iValue)

{

p_iValue = 9;

}

int main()

{

int iValue = 8;

int iValue1 = 8;

setValue(iValue);

printf("value=%d\n", iValue); //结果为10

setValue1(iValue1);

printf("value1=%d\n", iValue1); //结果还是8

return 0;

}

6、将引用作为函数参数有哪些特点

一是,使用引用传递参数是直接对实参本身进行操作,当需要在函数内部修改传递进来的变量并传出去时,可使用引用;

二来,引用是无需重新分配存储空间的,但指针却需要,所以有时使用引用会更有效率;

7、什么时候需要使用常引用

当既要使用引用提高程序的效率,又不能在函数内部修改实参的值时,可使用常引用。

8、将引用作为函数返回值类型的好处和需遵循的规则

好处:在内存中不产生被返回值的副本

需遵循的规则:

(1)不能返回局部变量的引用;

(2)不能返回函数内部动态分配的变量的引用,因为引用只是作为一个临时变量的出现,并未赋予一个实际的变量,该引用所指向的空间无法被释放;

(3)可以返回类成员的引用,但最好是const类型;

(4)为了保证连续使用流操作符(<< >>)重载返回值时,操作的是同一个对象,流操作符重载返回值应该声明为引用

(5)+-*/这四则运算符不能返回引用

9、引用和多态的关系

引用是c++中另外一种实现多态的手段,与指针一样,也是基类的引用可指向派生类的实例。

引用实现多态的demo如下:

#include

#include

class CPerson

{

public:

CPerson()

{

height = 170;

weight = 120;

memset(sex, 0, sizeof(sex));

}

~CPerson(){}

virtual void SetSex()

{

strncpy(sex, "人", sizeof(sex)-1);

}

void PrintSex()

{

printf("我的性别是:%s\n", sex);

}

private:

int height;

int weight;

//此处sex不能是私有,否则子类中无法使用,因为子类对父类的私有成员有继承权,但没有使用权,也就是只能看,不能摸

protected:

char sex[8];

};

class CMan : public CPerson

{

public:

CMan(){}

~CMan(){}

void SetSex()

{

strncpy(sex, "男人", sizeof(sex)-1);

}

};

int main()

{

CMan cman;

CPerson *pPerson = &cman;

pPerson->SetSex(); //此处调用的是子类的SetSex

pPerson->PrintSex();

return 0;

}

10、引用和指针的区别

指针通过某个指针变量指向某个对象后,对指针所指向的对象间接操作;

引用本身就是变量的别名,所以对引用操作就是直接对所指向的变量进行操作;

引用不会重新分配存储空间,但指针却需要重新分配存储空间;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值