C\C++常见基础面试题目(1)

1. C++面向对象语言有哪三个主要特征。

答:封装、继承与多态性。

2. 类中const、reference、或某个类类型成员变量在哪里进行初始化?

答:只能通过构造函数初始值列表进行初始化。

3. .h头文件中的ifndef/define/endif作用。

答:防止头文件重复包含

4. #include<file.h>和#include "file.h"的区别?

答:前者是从标准库中开始寻找头文件,后者是从当前工程目录下开始查找。

5. 一个指针可以是volatile吗?

答:可以。

6. main函数执行之前还会执行什么代码?

答:全局对象的构造函数会在main函数之前执行。

7. 两个整型变量a和b,不使用if、switch或其它判断语句,找出最大值。

答:(a+b+abs(b-a))/2

8. 在不用第三方参数的情况下,交换两个参数的值。

答:a = a + b; b = a - b; a = a -b;

9. int i = 5, b = 7; cout << (i++ + b) <<endl; 不用调试,请说出执行结果。

答:12。

备注:因为后置递增运算符的优先级高于二元加法。而且后置递增运算符是返回递增前的值。

前置递增/递减:首先将运算对象加1(或减1),然后将改变后的对象作为求值结果;后置递增/递减:将运算对象加1(或减1),但求值结果是运算对象改变之前那个值的副本。前置版本将对象本身作为左值返回,而后置版本则将对象原始值的副本作为右值返回。

10. 说说这三种描述的区别:(1)const char *p(2); char const *p; (3)char * const p;。

答:(1)和(2)是一样的,p都是执行const char的指针,可以改变p的值,但不能通过*p的方式来修改指向的值;

       (3)p指针是个指向char的常量指针,不能修改p的值,但可以通过*p的方式来修改指向的值;

11. 以下代码能够编译通过吗?为什么?

unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[size2];

答:str2编译出错。

备注:数组中元素个数也属于数组类型的一部分,编译的时候维度必须是已知的。维度必须是一个常量表达式。

12. 分别写出bool,int,float和指针类型的变量a与“零”的比较语句。

布尔变量与零值比较:

if (a)或if (!a)

整型变量与零值比较:

if (a == 0)或if (a != 0)

浮点变量与零值比较:

无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与任何数字比较,应该设法转化成“>=”或“<=”形式。

应当将

if (a == 0.0) // 隐含错误的比较

转化为

if ((a>=-DBL_EPSILON) && (a<=DBL_EPSILON)) 或者 if (abs(a) <= DBL_EPSILON)

在C++中,则可以用numeric_limits模板类的epsilon方法获取到

numeric_limits<float>::epsilon() 返回FLT_EPSILON

numeric_limits<double>::epsilon() 返回DBL_EPSILON

指针变量与零值比较

if (a == NULL)或if (a != NULL)     // a与NULL显式比较,强调a是指针变量

13.  假定x = 9999,求下面函数的返回值

int func(x)
{
    int countx = 0;
    while (x)
    {
        countx++;
        x = x&(x-1);
    }
    return countx;
}

答案:8

思路:将x转化为2进制,看含有的1的个数。

14. 以下代码能输出0吗?为什么?

struct CLS
{
    int m_i;
    CLS(int i) : m_i(i) {}
    CLS()
    {
        CLS(0);
    }
};

int main()
{
    CLS obj;
    cout << obj.m_i << endl;
    return 0;
}

答:不能。

在默认构造函数内部再调用带参的构造函数属用户行为而非编译器行为,亦即仅执行函数调用,而不会执行其后的初始化表达式。只有在生成对象时,初始化表达式才会随相应的构造函数一起调用。

15. ①return String(s1 + s2);和②String temp(s1 + s2); return temp; 一样吗?

答:

①这是临时对象的语法,表示“创建一个临时对象并返回它”。

②将发生三件事。首先,temp对象被创建,同时完成初始化;然后拷贝构造函数把temp拷贝到保存返回值的外部存储单元中;最后,temp在函数结束时被销毁(调用析构函数)。然而“创建一个临时对象并返回它”的过程是不同的,编译器直接把临时对象创建并初始化在外部存储单元中,省去了拷贝和析构的化费,提高了效率。

16. 下列程序输出结果是什么?

inline void max_out(int val1, int val2)
{
    cout <<(val1 > val2) ? val1 : val2;
}

int main()
{
    int ix = 10, jx = 20;
    cout << "The larger of " << ix;
    cout << ", " << jx << " is ";
    max_out(ix, jx);
    cout << endl;
}

答:The larger of 10, 20 is 0

为什么不是20呢?问题在于输出操作符的优先级高于条件操作符,所以输出的是val1和val2比较结果的true/false。

应该改成:cout <<((val1 > val2) ? val1 : val2);

17. 为什么需要使用堆?使用堆空间的原理?

答:直到运行时才知道一个对象需要多少内存空间;不知道对象的生存期到底有多长。

18. 类的构造函数可不可以是纯虚函数?

答:类的构造函数不能定义为虚函数。析构函数可以。

19. 如果基类的析构函数不是虚函数会带来什么问题?

答:delete一个指向派生类对象的基类指针时,派生类的析构函数不能正常调用,可能会造成内存泄漏。

20.  写出条件运算符(?:)的形式。

形式:cond ? expr1 : expr2;
示例:string finalgrade = (grade < 60) ? "fail" : "pass";
备注:三元表达式(?:)问号后面必须是同一类型。

21. 如何打印出当前源文件的文件名以及源文件的当前行号?

cout << __FILE__ ;			// 存放文件名的字符串字面值
cout <<__LINE__ ;			// 存放当前行号的整型字面值
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。(C语言也有)
__func__					// 函数名
__TIME__					// 存放文件编译时间的字符串字面值
__DATE__					// 存放文件编译日期的字符串字面值

22. assert宏。

答:assert(expr);

断言assert是一种预处理宏,定义在cassert头文件中。首先对expr求值,如果表达式为假(即0),assert输出信息并终止程序的执行。如果表达式为真(即非0),assert什么也不做。assert只在DEBUG模式下起作用。

23. int (*s[10])(int)表示的是什么?

答:函数指针数组,每一个指针都指向int Func(int)这样的函数。

24. 变量的声明和定义有什么区别?

答:为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但只能在一个地方定义。加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。

25. 写一个标准宏MIN

#define MIN(a, b) ((a)<=(b) ? (a):(b))

26. a和&a有什么区别请写出以下代码的打印结果,主要目的是考察a和&a的区别。

#include<stdio.h>

int main( void )
{
    int a[5] = {1, 2, 3, 4, 5};
    int *ptr = (int *)(&a+1);
    printf("%d,%d", *(a+1), *(ptr-1));
    return 0;
}

输出结果:2,5

解析:数组名a可以作数组的首地址,而&a是数组的指针,指针ptr指向数组地址的下一块空间,通过*(ptr-1)就可获取数组的最后一个值。

27. 引用和指针有何区别?

(1)引用必须被初始化,指针不必。

(2)引用初始化以后不能被改变,指针可以改变所指的对象。

(3)不存在指向空值的引用,但是存在指向空值的指针。

28. 写出下列代码运行结果

char str[] = "world";
cout << sizeof(str) << ": ";

char *p = str;
cout << sizeof(p) << ": ";

char i = 10;
cout << sizeof(i) << ": ";

void *pp = malloc(10);
cout << sizeof(pp) << ": ";

int arr[10] = {1,2,3};
cout << sizeof(arr) << endl;

答:6: 4: 1: 4: 40

29. sizeof和strlen之间的区别

(1)sizeof是获得一个变量或者类型的大小(以字节为单位),而strlen计算字符串的长度,不包括’\0’在内;

(2) sizeof是运算符,strlen是函数;

(3) sizeof可以用类型做参数,strlen只能用char*做参数,且必须是’\0’作结尾的;

(4) 数组作sizeof参数时不会转化为指针,但是传递给strlen就退化为指针;

(5) 大部分编译器在编译时就把sizeof计算过了,是类型或是变量的长度。strlen的结果要在运行时才计算出来。

(6)sizeof操作符不能返回被动态分配的数组或外部的数组的尺寸。

30. 说说new、delete、malloc、free的关系

答:malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。但new会调用构造函数,delete会调用对象的析构函数。对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。不能将执行构造函数和析构函数的任务强加于malloc和free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

31. delete与delete[]区别?

答:delete与new配套,delete[]与new[]配套使用。delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数。

32. 在C++程序中调用被C编译器编译后的函数,为什么要加extern “C”?

答:extern “C”表示调用C语言编写的函数。C++使用链接指示指出任意非C++语言函数。除extern “C”外,比如还有extern “Ada”,extern “FORTRAN”,分别表示使用Ada语言编写的函数和使用FORTRAN语言编写的函数。

      C++提供了C连接交换指定符号extern “C”解决名字匹配问题。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值