C++ 面试基础1

这篇博客主要介绍了C++面试中的基础知识点,包括内存管理、虚函数、类型安全、内联函数、静态成员变量、模板类、函数重载、析构函数的使用、指针与数组的操作,以及如何利用C++编写程序判断操作系统位数等。还讨论了函数指针、malloc与new的区别,以及在编写高效代码时的一些注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. int var[sizeof(unsigned int)]; 是否正确,为什么?

正确,sizeof是编译时运算符,在程序编译时就确定了其值,可以sizeof(unsigned int)看作是与机器相关的常量。

2.源文件中定义的静态全局变量(或者称静态外部变量)其作用域范围是?

源文件中定义的静态全局变量只在该源文件中有效,只能被该源文件内的函数使用,同一源程序中的其他源文件不能使用它,可以避免在其他源文件中引起错误。

3.C++中的virtual 和 inline的函数是什么?

virtual:在基类成员函数中将函数声明为virtual则表示该成员函数为虚函数,其派生类可以重新定义从基类继承的该虚函数,以实现多态。
inline: inline与函数的定义(实现)放在一起,使得该函数称为内联函数,使用内联函数的目的是为了提高函数的运行效率。内联函数的函数体的代码不能过长,因为内联函数省去函数调用的时间是以代码膨胀为代价的。内联函数不能包含循环语句,因为循环语句的开销大。inline是用于实现的关键字,而不是用于声明的关键字。

4. VC中,编译工具栏中Debug和Release选项的含义是什么?

Debug称为调试版本,包含大量调试信息,编译器不对代码作优化,以便于程序员调试。
Release称为发布版本,编译器对其进行了各种优化,使得程序在代码大小和运行效率上是最优的,以便用户良好的使用。

5. 如果在申请动态内存时找不到足够大的内存块,malloc和new将返回NULL指针,宣告内存申请失败,那么该如何处理这种情况?

  • 方法1:判断指针是否为 NULL,如果是则马上用return 语句终止本函数。
  • 方法2:判断指针是否为 NULL,如果是则马上用 exit(1)终止整个程序的运行 。
  • 方法3:为 new 和 malloc 设置异常处理函数。例如 Visual C++可以用_set_new_hander 函数为 new 设置用户自己定义的异常处理函数,也可以让 malloc享用与 new 相同的异常处理函数。

6.C++是不是类型安全的?

不是,两个不同类型的指针可以进行强制转换(reinterpret cast).

Java是强类型语言,是类型安全的,编译器会对代码进行检查,确保变量的每一次赋值,方法的每一次调用都是符合类型的。如果有任何不想符合的情况,Java编译器就会给出错误。Java 程序不可能将本来属于一种类型的变量当作另外一种类型处理,因此不会产生由此引发的错误。

简而言之,Java语言通过以下3点实现类型安全:

  • 编译期间的类型检查;
  • 自动的存储管理;
  • 数组的边界检查。

7. const char *p, char const * p,char * const p 的区别?

  • const char * p : p是一个指向const char的指针,p是可以改变指向的,但是p指向的内容是不能改变的;
  • char const * p:同 const char * p表达的意义是一样的;
  • char * const p :p是一个指向char的const指针,该指针是不可改变的,但是p指向的内容是可以改变的;

8.如何用C++写个程序,如何判断一个操作系统是16位还是32位的?

定义一个指针p,打印出sizeof§,如果节果是4,则表示该操作系统是32位,打印结果是2,表示是16位。

8.用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof操作符

int a = ~0;
if( a>65536 )
{
cout<<"32 bit"<<endl;
}
else
{
cout<<"16 bit"<<endl;
}

9. malloc 和 new的区别?

  • malloc是库函数,不在编译器控制范围之内;调用malloc时,从堆中申请内存;
  • new是运算符,在编译器控制范围之内。调用new时,从堆中申请内存并为内存调用构造函数;

10.C++ 中有没有纯虚构造函数?

构造函数不能是虚函数,析构函数可以是虚函数(或者纯虚函数)

11.函数指针的辨析

  • void * ( *(*fp1)(int))[10];

    fp1是一个指针,指向一个函数,这个函数的参数为int型,函数的返回值是 一个指针,这个指针指向一个数组,这个数组有10个元素,每个元素是一个void*型指针。

  • float (( fp2)(int,int,int))(int);

    fp2是一个指针,指向一个函数,这个函数的参数为3个int型,函数的返回值是一个指针,这个指针指向一个函数,这个函数的参数为int型,函数的返回值是float型。

  • int (* ( * fp3)()) [10] ();
    fp3是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是一个指针,这个指针指向一个数组,这个数组有10个元素,每个元素是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是int型。

12.在C++的一个类中声明一个static成员变量有什么用?

在C++类的成员变量被声明为static(称为静态成员变量),意味着它为该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,也就是说不管创建多少对象,static修饰的变量只占有一块内存。其修改值为该类的其它所有实例所见;而类的静态成员函数也只能访问静态成员(变量或函数)。 static是加了访问控制的全局变量,不被继承。

13.C++中为什么用模板类。

  • (1)可用来创建动态增长和减小的数据结构
  • (2)它是类型无关的,因此具有很高的可复用性。
  • (3)它在编译时而不是运行时检查数据类型,保证了类型安全
  • (4)它是平台无关的,可移植性好
  • (5)可用于基本数据类型

14.函数重载,我们靠什么来区分调用的那个函数?靠返回值判断可以不可以?

如果同名函数的参数不同(包括类型、顺序不同) ,那么容易区别出它们是不同的。如果同名函数仅仅是返回值类型不同,有时可以区分,有时却不能。例如:

void Function(void);
int Function (void);

上述两个函数,第一个没有返回值,第二个的返回值是 int 类型。如果这样调用函数:

int x = Function ();

则可以判断出 Function 是第二个函数。问题是在 C++/C 程序中,我们可以忽略函数的返回值。在这种情况下,编译器和程序员都不知道哪个Function 函数被调用。 所以只能靠参数而不能靠返回值类型的不同来区分重载函数。

15.基类的析构函数不是虚函数,会带来什么问题?

派生类的析构函数用不上,会造成资源的泄漏. ???

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

cout << FILE ;
cout << LINE ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。( c也有)

17.写一个函数计算当参数为n(n很大)时的值 1-2+3-4+5-6+7…+n。

long  func(long n)
{
	if(n <= 0)
	{
		printf("error: n must > 0);
		exit(1);
	}
	if(0 == n % 2)
		return (n / 2) * (-1);
	else
		return (n / 2) * (-1) + n;
}

18.以下三条输出语句分别输出什么?

char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 输出什么?
cout << boolalpha << ( str3==str4 ) << endl; // 输出什么?
cout << boolalpha << ( str5==str6 ) << endl; // 输出什么?

输出: false,false,true.
str1和str2都是字符数组,每个都有其自己的存储区,它们的值则是各存储区首地址,不等; str3和str4同上,只是按const语义,它们所指向的数据区不能修改。 str5和str6并非数组而是字符指针,并不分配存储区,其后的“abc”以常量形式存于静态数据区,而它们自己仅是指向该区首地址的指针,相等。

19.以下代码会输出0么?为什么?

struct Test
{
	int data;
	Test( int i ) : data(i) {}
	Test(){
		Test(0);
	}
};

Test obj;
cout << obj.data << endl;

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

20. return 语句使用注意事项

  • return 语句不可返回指向“栈内存”的“指针”或者“引用” ,因为该内存在函数体结束时被自动销毁;
  • 要搞清楚return语句返回的究竟是“值” 、 “指针”还是“引用” ;
  • 如果函数返回值是一个对象,要考虑 return 语句的效率;

21.return String(s1 + s2); 和 String str(s1 + s2); return str; 一样吗?

  • return String(s1+s2) : 表示创建一个临时对象并返回它,编译器直接把临时对象创建并初始化在外部存储单元中,省去了拷贝和析构的花费,提高了效率;
  • String str(s1 + s2); return str; :(1)str 对象被创建并完成初始化;(2)拷贝构造函数把 str 拷贝到保存返回值的外部存储单元中;(3)str在结束函数结束时被销毁;

22.下面程序的输出结果是什么?

#include <iostream>
using namespace std;

inline void max_out( int num1, int num2 )
{
	cout << ( num1 > num2 ) ? num1 : num2;
}

int main()
{
	int num1 = 10, num2 = 20;
	cout << "The larger of " << num1;
	cout << ", " << num2 << " is ";
	max_out( num1, num2 );
	cout << endl;
    return  0;
}

运行结果:
The larger of 10, 20 is 0

原因: 输出操作符的优先级高于条件操作符 所以输出 num1和 num2的比较结果false(0)

23.写出一个函数统计一个字节中1的个数

unsigned int NumOfOne(char data){
	unsigned int num=0, val;
	for(int i=0; i<8; i++)
	{
		val = data>> i; //移位
		val &= 0x01; //按位&
		if(val) num++;
	}
	return num;
}

24…编写一个函数,函数接收一个十六进制数组成的一个字符串,函数的功能是把接到的这组字符串转换成对应的十进制数字并将十进制数字返回

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

bool HexToDec( char * hex,int& dec )
{
	int len = strlen( hex );
	if( len>8 ) return false;

	int mid = 0;
    dec = 0;
	for(int i=0;i<len;i++ ){
		if( hex[i]>='0'&& hex[i]<='9' )
			mid = hex[i]-'0';
		else if( hex[i]>='a'&& hex[i]<='f' )
			mid = hex[i] -'a' +10;
		else if( hex[i]>='A'&& hex[i]<='F' )
			mid = hex[i] -'A' +10;
		else
			return false;
		mid <<= ((len-i-1)<<2); 
		dec =dec+mid;
	}
	return true;
}

int main(){
    char* hex="FFFFFFFF";
    int dec=0;
    bool result=false;
    result= HexToDec(hex,dec );
    if(result){
        cout<<"0X"<<hex<<": ";
        cout<<dec<<endl;
    }
    else
        cout<<"ERROR";
    return 0;
}

运行结果:
0xFFFFFFFF: -1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值