C++面试题

来源:互联网 发布:数控g72编程实例 编辑:程序博客网 时间:2024/04/29 08:48

过去收集的些C++面试题,写了答案和分析。如有错误,欢迎指出。
收集的试题只有部分是有答案,自己补上了剩下的答案并做了分析。如果不能算原创的话,请指出。

1. 以下三条输出语句分别输出什么?[C易]
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
字符串”abc”在常量区里只有一份。三组比较的都是地址:5,6为指向常量字符串的指针,所指向的地址相同。而前4个是将字符串的值复制
给栈上数组1~4,比较的是数组的首地址,各数组的地址不相同。



2. 非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等]
答:
a. class B : public A { ……} // B公有继承自A,可以是间接继承的
b. class B { operator A( ); } // B实现了隐式转化为A的转化
c. class A { A( const B& ); } // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A& operator= ( const A& ); // 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个



3. 以下代码中的两个sizeof用法有问题吗?[C易]
void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母
{
    for( size_t i=0; i
        if( 'a'<=str[i] && str[i]<='z' )
            str[i] -= ('a'-'A' );
}
char str[] = "aBcDe";
cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;
答:
函数里传数组时,数组会退化为指针,长度为地址长度4。后一个为5个字母加上字符串结束符‘/0’.



4. 以下代码有什么问题?[C难]
void char2Hex( char c ) // 将字符以16进制表示
{
    char ch = c/0x10 + '0'; if( ch > '9' ) ch += ('A'-'9'-1);
    char cl = c%0x10 + '0'; if( cl > '9' ) cl += ('A'-'9'-1);
    cout << ch << cl << ' ';
}
char str[] = "I love 中国";
for( size_t i=0; i
    char2Hex( str[i] );
cout << endl;
答:
用了char而非unsigned char,汉字可以出现80以上的编码,即负值,导致解析错误



5. 以下代码有什么问题?[C++易]
struct Test
{
    Test( int ) {}
    Test() {}
    void fun() {}
};
void main( void )
{
    Test a(1);
    a.fun();
    Test b();
    b.fun();
}
答:
Test b才是栈上对象使用默认构造函数的方法。而文中的被编译器解析为了函数申明。



6. 以下代码有什么问题?[C++易]
cout << (true?1:"1") << endl;
答:
1,“1”无法转换成同一类型。”1”为字符串 ‘1’和’/0’。三元运算符?:返回值需同一类型。



7. 以下代码能够编译通过吗,为什么?[C++易]
unsigned int const size1 = 2;
char str1[ size1 ];
unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[ size2 ];
答:
不能,temp不是常量。因此栈上数组无法确定大小



8. 以下代码中的输出语句输出0吗,为什么?[C++易]
struct CLS
{
    int m_i;
    CLS( int I ) : m_i(i) {}
    CLS()
    {
        CLS(0);
    }
};
CLS obj;
cout << obj.m_i << endl;
答:
输出值未定义。显示的调用构造函数实际上是创建一个该类型的新匿名对象,而不是初始化想要得那个对象。对象本身的m_i没有初始化。



9. C++中的空类,默认产生哪些类成员函数?[C++易]
答:
class Empty
{
public:
    Empty();                          // 缺省构造函数
    Empty( const Empty& );            // 拷贝构造函数
    ~Empty();                         // 析构函数
    Empty& operator=( const Empty& ); // 赋值运算符
    Empty* operator&();               // 取址运算符
    const Empty* operator&() const;   // 取址运算符 const
};

如果上述函数没有被使用到,也不会产生。




10. 以下两条输出语句分别输出什么?[C++难]
float a = 1.0f;
cout << (int)a << endl;
cout << (int&)a << endl;
cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
Float b = 0.0f;
cout << (int)b << endl;
cout << (int&)b << endl;
cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么?
答:
false,true
cout << (int&)b << endl;,这句话应该是直接使用int类型来输出b的内存地址里的数据。0.0f时float类型的内存段里的32bit都为0。
cout << (int)&b << endl是把b的地址转化为int值输出。

float的结构为
1个符号位,8个阶码位和23个尾数位

double为
1个符号位,11个阶码位,52个尾数位

浮点数的表示形式类似于 数学上的科学计数法,不过浮点数是二进制的。舍入法是向偶数舍入(指尾数二进制上的)
浮点数的详细内容参见 IEEE754 或 《深入理解计算机系统》第二版,2.4节



11. 以下反向遍历array数组的方法有什么错误?[STL易]
vector array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 3 );
for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍历array数组
{
    cout << array[i] << endl;
}
答:
array声明方法应该是vector<int> array.
循环里有问题,size_type为无符号整数,即永远大于等于0,循环永不结束。



12. 以下代码有什么问题?[STL易]
typedef vector IntArray;
IntArray array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 2 );
array.push_back( 3 );
// 删除array数组中所有的2
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
    if( 2 == *itor ) array.erase( itor );
}
答:
声明方法应该是vector<int>
迭代器失效。删除一个元素后,后面的元素前进移动,即第二个2没有删除



本试题仅用于考查C++/C程序员的基本编程技能。内容限于C++/C常用语法,不涉及数据结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不能反映考生的智力和软件开发能力。
笔试时间90分钟。请考生认真答题,切勿轻视。


一、请填写BOOL , float, 指针变量 与“零值”比较的 if 语句。(10分)

提示:这里“零值”可以是0, 0.0 , FALSE或者“空指针”。例如 int 变量 n 与“零值”比较的 if 语句为:

if ( n == 0 )
if ( n != 0 )
以此类推。

请写出 BOOL flag 与“零值”比较的 if 语句:
请写出 float x 与“零值”比较的 if 语句:
请写出 char *p 与“零值”比较的 if 语句:

答:
if ( flag )
if ( !flag )


如下写法均属不良风格,不得分。
If (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)

请写出 float x 与“零值”比较的 if 语句。(4分)

标准答案示例:
const float EPSINON = 0.00001f;
if ((x >= - EPSINON) && (x <= EPSINON)
不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”此类形式。

如下是错误的写法,不得分。
If (x == 0.0)
if (x != 0.0)

 

以上是标准答案,但浮点数的0是有严格定义的。正0.0,全比特位为0,负0.0,符号位为1,其他都是0。感觉题目应该去比较1.0之类的


请写出 char *p 与“零值”比较的 if 语句。(3分)

标准答案:
if (p == NULL) // 网上给出的标准答案是这么写的但个人觉得应该把NULL放在前面
if (p != NULL) // 这样如果漏了个=(NULL = p),编译器就能报错。


如下写法均属不良风格,不得分。
If (p == 0)
if (p != 0)

if (p)
if (!p)



二、以下为Windows NT下的32位C++程序,请计算sizeof的值(10分)
char str[] = “Hello” ;
char *p = str ;
int n = 10;
请计算
sizeof (str ) = 6 // 5个字母加结束符’/0’
sizeof ( p ) = 4  
sizeof ( n ) = 4
void Func ( char str[100])
{
请计算
sizeof( str ) = 4 // 函数参数,数组退化成指针
}

void *p = malloc( 100 );
请计算
sizeof ( p ) = 4


三、简答题(25分)
1、头文件中的 ifndef/define/endif 干什么用?
答:
防止头文件被重复引用。

2、#include <> 和 #include “filename.h” 有什么区别?
答:
<>用于标准头文件,””用于自定义头文件。两者的搜索路径不同


3、const 有什么用途?(请至少说明两种)
答:
常数,常数参数,常量成员函数。


4、在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”声明?
答:
已编译的C代码与已编译的C++代码格式不同,所以要告诉编译器某些函数是用C编写的,这样链接器就能适当地使用这些函数了。C++与C得符号规则不一样。



5、请简述以下两个for循环的优缺点
// 第一个
for (i=0; i++;)
{
if (condition)
DoSomething();
else
DoOtherthing();
}
// 第二个

if (condition)
{
for (i=0; i++;)
DoSomething();
}
else
{
for (i=0; i++;)
DoOtherthing();
}
答:
优点:每次循环时都会判断下条件,然后执行相应事件
缺点:每次都要进行判断,消耗资源
优点:只判断一次,然后循环执行相应事件
缺点:没法改变条件
这题也不知是谁想出来的?两种不同的需求,没什么可比性。



四、有关内存的思考题(20分)
void GetMemory(char *p)
{
p = (char *)malloc(100);
}

void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}

请问运行Test函数会有什么样的结果?
答:
函数时按值传递了一个指针变量。函数里改变的是指针副本p的值,使其指向所申请的内存,而str仍然指向NULL。之后试图对NULL地址做写入操作,内存访问违规



char *GetMemory(void)
{
char p[] = "hello world";
return p;
}

void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}

请问运行Test函数会有什么样的结果?
答:
野指针,结果未定义。函数中的字符串是栈上的局部变量,函数退出后,局部变量也就销毁了。



void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}

void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}

请问运行Test函数会有什么样的结果?
答:
程序完全正确,子函数利用参数(地址)成功的为主函数申请了动态内存



void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}

请问运行Test函数会有什么样的结果?
答:
野指针,结果未定义。动态内存被free掉之后,但指针仍指向之前的地址,成为野指针。


五、编写strcpy函数(10分)
已知strcpy函数的原型是
char *strcpy(char *strDest, const char *strSrc);
其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数 strcpy
(2)strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值?

答:

返回char*是为了方便代码链式写法。比如:
strcpy(str1,strcpy(str2,str3));


六、编写类String的构造函数、析构函数和赋值函数(25分)
已知类String的原型为:
class String
{
public:
String(const char *str = NULL) // 普通构造函数
{
  if(NULL == str)
    m_data = NULL;
  else
  {
    m_data = new char[strlen(str) + 1];
    strcpy(m_dara, str);
    m_data[strlen(str)] = ‘/0’;
  }
};

String(const String &other) // 拷贝构造函数
{
  if(NULL == other.m_data)
  m_data = NULL;
  else
  {
    m_data = new char[strlen(other.m_data) + 1];
    strcpy(m_dara, other.m_data);
    m_data[strlen(other.m_data)] = ‘/0’;
  }
};

~ String(void) // 析构函数
{
  delete[] m_data;
  m_data = NULL;
};

String & operate =(const String &other) // 赋值函数
{
  if(&other == this)
    return *this;
  else
  {
    delete m_data;
    if(NULL == other.m_data)
       m_data = NULL;
    else
    {
      m_data = new char[strlen(other.m_data) + 1];
      strcpy(m_dara, other.m_data);
      m_data[strlen(other.m_data)] = ‘/0’;
    }   
  }

};

private:
char *m_data; // 用于保存字符串
};

请编写String的上述4个函数。

题目出自http://www.ad0.cn/
题目出自网魂工作室http://www.ad0.cn/