首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

4道稍微高级点的c++面试题,供菜鸟一窥门径

2012-03-13 
4道稍微高级点的c++面试题,供初学者一窥门径1.写出下面程序的输出classabcvoiddel(abc*pobj){deletepobj

4道稍微高级点的c++面试题,供初学者一窥门径
1.写出下面程序的输出

class   abc;
void   del(abc   *pobj){
  delete   pobj;
}

class   abc{
public:
  abc(){
    printf( "abc\r\n ");
  }
  ~abc(){
    printf( "~abc\r\n ");
  }
};


int   main()
{
  abc   *pobj   =   new   abc;
  del(pobj);
}


2.写出下面程序的输出

void*   operator   new(size_t   size)
{
  printf( "malloc   %u\r\n ",   size);
  return   malloc(size);
}
void   operator   delete(void   *memblock){
  printf( "free\r\n ");
  return   free(memblock);
}

class   abc{
public:
  abc(){
    printf( "abc\r\n ");
    throw   int();
  }
  ~abc(){
    printf( "~abc\r\n ");
  }
};

int   main(){
  try{
    new   abc;
  }catch(int&   i){
    printf( "%d\r\n ",   i);
  }
  return   0;
}


3.写出下面程序的输出

template   <typename   T>
class   abc{
public:
  abc(){
    printf( "primary\r\n ");
  }
};

template <>  
abc <int> ::abc(){
  printf( "member   spec\r\n ");
};

template <typename   T,   typename   P>
class   abc <T   (*)(P)> {
public:
  abc(){
    printf( "partial   spec\r\n ");
  }
};

int   main()
{
  abc <void*   (*)(int)>   f_abc;
  abc <int>   i_abc;
}


4.下面的代码能否通过编译?为什么

class   a{
public:
  virtual   ~a(){
  }
private:
  void   operator   delete(void   *p);
};

int   main()
{
  a   _1;
}



[解决办法]
1 abc
2 malloc 40
malloc 30
malloc 1
abc
free
0
free
free


[解决办法]
1.abc
但是不是很明白
2.malloc 1
abc
free
0
考察的是重载operator new和delete,以及类内存分布,异常
3.partial spec
member spec
这题猜的,这样的模板方法没见过
4.不能,会默认去调delete,结果没有
[解决办法]
4.不是没有,是private的,写错
[解决办法]
先回答,再验证。

1、
abc,出错!
2、
malloc 4
abc
0
3、
partial spec
member spec
4、
可以,栈变量,构造、析构函数均可访问。
[解决办法]
其他的没什么好说的, 不过我觉得第四题的答案可能是不确定的, 可以在VC6中试试.

有时你重载了一个operator new, 不管你有没有调用, 一运行程序, 就会崩溃.
可能是因为不仅仅你自己的代码调用了你的operator new, 而且编译器自已嵌入进来的代码也调用了, 而这时异常发生了.
[解决办法]
弱弱的问一下, 为什么第一题不是输出:abc, ~abc
而是报错?
------解决方案--------------------


试了一下, 会有连接错误, 因为operator delete 示定义.
[解决办法]
delete 指针
这不是语法就是这样吗, 怎么还要重载? 初学, 请教
[解决办法]
FrogOfCT(向往自由),请查阅C++ Primer相关章节
或Effective C++
[解决办法]
第一题考的还是比较特殊,觉得编译器太傻,
难道声明仅仅作类型检查,如果做多遍编译的话可能效率有问题.
第四题题好象没出好,delete应该有一个定义吧.
[解决办法]
mark
[解决办法]
第2题靠异常的stack unwinding
[解决办法]
第二题怎么靠stack unwinding?请解释下。

[解决办法]
刚用VS2005想试验看看,第一个编译也通不过。

从提示的消息来看,原因大概是调用 delete pobj需要知道析构函数的定义
不知道搂上的几位有没有这个问题?
[解决办法]
1 abc (定义del函数的时候,abc的析构函数未定义,因此不会调用)

3partial spec
member spec
应该是模板部分特化吧。

2和4,不会,没仔细看过operator
2估计的输出是
malloc
abc
0
[解决办法]
stack unwinding大意是出现异常的时候由异常处理机制自动调用堆栈对象的析构函数
[解决办法]
堆栈对象-> 2题中的是堆对象啊……
[解决办法]
mark
不错..
[解决办法]
1,abc,但是释放内存没成功,内存泄露,要用双指针**

[解决办法]
mark
[解决办法]
1。定义了2个同名的类, Del函数中 是按照第1个类处理,而 main中按照下面1个处理。
给第1个abc类你定义一下析构函数你就会发现析构的时候跑到第1个里面去了。
严格的说
答案是:abc 错误。
2.delete中 void 又定义了return ,有毛病。去掉retrun 只留 free。
malloc 40 malloc 33 malloc 1 abc free 0 free free
重载了new和delete,从开始进去申请空间就开始打屏。
3。4。int main 有没返回,恶心,第4。中delete没有写实现,出错。
第3。恶心,不想看。
[解决办法]
第4: void operator delete(void *p){}; 完成实现 ,就对了。{}也是实现方法,哈哈。
[解决办法]
第4是程序没写完。 delete 不会被调用。
[解决办法]
up
[解决办法]
第3题 我看了一下,class abc <T(*) (P)> 是什么 费解, 前后又定义了2个同名的类,
看书中。。
[解决办法]
3题:
C++ primer 3版 704页
类模版部分特化。
抄过来,怎么编译不通,昏死了。
[解决办法]
关于第2题:
《More Effective C++》条款10: 在构造函数中防止资源泄漏
……不用为BookEntry中的非指针数据成员操心,在类的构造函数被调用之前数据成员就被自动地初始化。所以如果BookEntry构造函数体开始执行,对象的theName、theAddress和thePhones数据成员已经被完全构造好了。这些数据可以被看做是完全构造的对象,所以它们将被自动释放,不用你介入操作。……
——————————————————————————————————————————
上文中提到的“它们将被自动释放”可能就意味着当构造函数抛出异常时,会调用delete函数以释放内存,否则,c++不会允许构造函数抛出异常。
[解决办法]
1. abc

2.
malloc 1
abc
free
0

3.(没把握)
partial spec
member spec

4.编译通不过

先去验证一下,然后把答案详解马上帖上来。



[解决办法]
第二题有意思


考到了异常的处理


但是很多人在异常这方面都是很薄弱的


sinall() 的解释应该是对的,


学习学习~
[解决办法]
VS2005下
1) abc
2) abc
0
3) partial spec
member spec
4) 编译不过,delete没有实现
[解决办法]
详解:
第1题:
首先要了解 new (即new operator)、 operator new 以及 delete(即delete operator)、operator delete的差别,这个网上搜一下不多说了。

调用delete后按理应该是先调用析构函数然后调用operator delete释放内存。
但是void del(abc *pobj)原型中的abc使用的是前向声明,在编译器编译del函数的时候还不知道class abc的实际内容,当然也不知道其析构函数的地址。

可以看一下反汇编代码,就非常清楚了,delete函数内只调用了operator delete,没调用abc的析构函数。

如果删除class abc的前向声明删了,把del函数放到class abc声明后就ok了。
[解决办法]
2题
其实就是把成员对象逆向西够了

4ti
成员delete遮盖了全局delete的名字,而它本身没有定义,link error


[解决办法]
2)应该是
malloc 1
abc
free
0
[解决办法]
观望中 .........
[解决办法]
3题死都编译不过。
VC6.0 不过
VS2005 不过
VS2003不过。。 气死人。。。。
[解决办法]
第2题:
在C++中,构造函数抛出异常后不会出发析构函数的调用,这和object pascal不一样。
c++认为构造失败意味着对象没有产生,既然没有生就没有死。
但是对于在堆中分配内存的对象就不是这样了,似乎系统会替你调用delete。有点类似auto_ptr的方式。

对此我没有找到证据,有时间在反汇编调试一下,看看系统做了什么操作。

对于sinall() 说的“它们将被自动释放”,可能你理解错了,“theName、theAddress和thePhones数据成员已经被完全构造好了”,既然构造成功了,就不会出现不调析构函数的问题,theName、theAddress和thePhones不是new出来的,和delete没关系。
[解决办法]
第4题,在 2005下通过
输出为。
partial spec
member spec

[解决办法]
ls写的是第三题
[解决办法]
mark 一下
[解决办法]
第3题:对模版不是很熟,知道的达人回答吧。
第4题:
难度较高,如果对动态创建及销毁对象很清楚的人来说可能知道。
如果对象是动态创建(也就是new出来的),那么在delete的时候系统会先调析构函数然后调operator delete,这个我前面已经提到过了。
编译器在编译的时候会把这2个步骤合并到一个函数里,看反汇编就知道了,函数名字类似
`scalar deleting destructor '。如果只是声明了operator delete函数而没有定义,那么编译的时候会得不到函数地址,这样生成`scalar deleting destructor '内置函数的时候就会报错了。

vs2003上编译了一下,错误提示如下:
test error LNK2019: 无法解析的外部符号 "private: static void __cdecl a::operator delete(void *) " (??3a@@CAXPAX@Z) ,该符号在函数 "public: virtual void * __thiscall a::`scalar deleting destructor '(unsigned int) " (??_Ga@@UAEPAXI@Z) 中被引用

至于为什么是static的就不用说了吧,呵呵。。

[解决办法]
第4题,在VC++6.0通不过

[解决办法]
MARK
[解决办法]
To heezhen:
第一题解释讲的很好,呵呵
To wangzhangyong411:
第一题内存可以释放掉,如果是用函数申请内存就要注意了,可能是分配给了指针的副本,所以分配内存时要用双指针。

[解决办法]
将前面几位的看了一下,也在机器上试验了一下,结果如下:

1.
abc (定义del函数的时候,abc的析构函数未定义,因此不会调用)
将del函数修改了一下,不过结果还是不变的。
void del(abc *&pobj)


{
delete pobj;
pobj = NULL;
}
这题还是留有疑问,但是80%赞同这个答案。
class abc;这个del函数之前的,应该算是类声明吧?

2.
#include <stdio.h>

class abc{
public:
abc(){
printf( "abc\r\n ");
throw int();
}
~abc(){
printf( "~abc\r\n ");
}
};

int main()
{
size_t s = sizeof(abc);
printf( "%d\n ",s);
}
经过测试(VC6,VC2005,MSYS&MINGW),输出为1,应该是一个空,static和unstatic member function都是在类的外部,不占类的空间。
operator new重载全局new,所以下面构造的时候new肯定会调用该operator new
operator delete同样。
至于size已经验证过了,所以对new来说,为malloc 1.
new分配完内存后,会自动调用构造函数,所以输出abc.
在构造函数内部,抛出异常,throw int();
对这点不了解,首先是异常机制,其次是构造函数中的异常是否有所不同。
Anyway,catch住这个异常,所以会输出i,为0.
但是在catch输出之前,因为异常出错,此时new分配内存的工作已经完成,如果不进行delete的话,势必会内存泄露。经过实验(VS2005,VC6会报错,因为operator delete返回值为void,但是使用了return,将return去掉后结果与VS2005一致),会在catch输出i之前调用,输出free.
所以第二题输出为:
malloc 1
abc
free
0

3.
类模版部分特化,不懂,不过看结果,能猜到 :)

4.
class a{
public:
virtual ~a(){
}
private:
void operator delete(void *p) {} ------------//修改了一下,加上了实现
};

int main()
{
a _1;
}

在修改前,无法编译通过,因为main中这样定义的话,是在栈中的变量,push和pop的时候会自动调用new和delete,而发现delete未实现,所以有link错误。(试验环境:VS2005,VC6)

修改后,调用正常,不解。
sinall()的回复似乎有点帮助:
关于第4题,有以下现象:
1)如果一个类有虚析构函数的话,那么自定义delete函数必须有函数体。
2)这个题目中,并不会调用delete函数。

那么,结论可能是虽然对于本题,delete函数不被调用,但是编译器需要它……,至于使用它干什么,不知道啊不知道。
[解决办法]
UPJF
[解决办法]
mark
[解决办法]
1.

abc
~abc

2.

abc
0

3.

primary
member spec

4.

可以
[解决办法]
#- -
[解决办法]
第1题用VS2005编译通过
结果
abc
[解决办法]
对2题进行测试发现在保留原有的外部函数的情况下,其class abc的size是33
在去除外部函数的情况下是1
但如果在主函数的第一行打印加“cout < < sizeof(abc) < < endl; "
输出的结果是
malloc 33
free
free
malloc 24
malloc 33
malloc 33
malloc 1
malloc 6
malloc 5
free
free
1
malloc 1
abc
free
0
free
free
free
free
free
free
free


未加时的结果是
malloc 40
malloc 33
malloc 1
abc
free
0
free
free

所以还要请教各位高手,这是怎么回事

[解决办法]
第一题
#include <cstdio>

using namespace std;

class abc;

void creatABC(){
abc a;
}

void del(abc *pobj) {
delete pobj;
}

class abc {
public:
abc() {
printf( "abc\r\n ");
}
~abc() {
printf( "~abc\r\n ");
}
};

delete只声明未定义的类时,因为没有析构函数而报了一个警告。
在createABC() 中构造abc的一个对象a (构造一个只声明还未定义的类时),编译器却报了一个错误。
看来类的创建要类的删除来的重要,因为可能先有鸡才能有蛋:)
[解决办法]
第二题:
C++的异常机制保证,try里的代码发生异常,对象会得到析构


即使构造函数中发生了异常,还是会调用析构函数.
[解决办法]
第一题 TC编译不过 BC可以 输出abc
第二题 在BC下是 malloc 8
abc
然后出现异常对话框 死掉了
VS.NET下 是malloc 1
abc
free
0


[解决办法]
第二题
void* operator new(size_t size)
{
printf( "malloc %u\r\n ", size);
return malloc(size);
}
void operator delete(void *memblock){
printf( "free\r\n ");
return free(memblock);
}
这两个外部函数应该把原有的内存分配和释放运算符覆盖了(原来的是怎么样,偶不清楚)
在这两个函数以下定义的类编译时new和delete的函数地址被这两个函数的地址取代了,所以当类在构造时,就调用了这个new函数(自定制的内存分配器)


[解决办法]
mark
[解决办法]
template <typename T>
class abc{///这里称为主模板
public:
abc(){
printf( "primary\r\n ");
}
};

template <>
abc <int> ::abc(){//这里称为对主模板的特化
printf( "member spec\r\n ");
};

template <typename T, typename P>
class abc <T (*)(P)> {///这里称为对主模板的偏特化
public:
abc(){
printf( "partial spec\r\n ");
}
};

int main()
{
abc <void* (*)(int)> f_abc;///按最匹配原则,调用第三个偏特化模板
abc <int> i_abc;//按最匹配原则,调用第二个特化模板
}

[解决办法]
哈,看了ls的回复,终于想起来这个最匹配原则了,原来还是看过的,不过忘了 :)
[解决办法]
第2题那个abc类的大小忘记说了,这个大小对于标准C++来说勿庸置疑就是1。
记住,函数不占类空间,只有非静态的数据成员才占类空间。
如果一个类成员都没有,如果实例话该类的话总要分配内存的,所以C++就约定放一个char。

关于这个问题记得在《c++对象模型》的第一章里面讲的很清楚了,大家可以参考。
[解决办法]
为什么第二道题在vc6下运行时候,出现了malloc40 和malloc33呢??请达人缘由示之。
[解决办法]
我的VC6+SP6为
malloc 1
楼上打个sp6补丁看看
[解决办法]
1. abc

2. malloc 1
abc
free
0

3. partial spec
member spec

4. 不能通过编译
[解决办法]
为什么第二道题在vc6下运行时候,出现了malloc40 和malloc33呢??请达人缘由示之。
=====================
VC6的连接有点特殊.
当重载了全局new和delete后,早于main运行的local对象的初始化也会调用到重载的new和delete,所以多产生这两句:malloc40 和malloc33
[解决办法]
各位可以在main的花括号处设断点,可以看到,在进入main前malloc40 和malloc33已经输出了.
[解决办法]
2、4题还请高手、版主友情解释一下!!!
[解决办法]
第2题可以在 < <More effective C++> > Item 27里找到答案.
第4题还是希望牛人来解释一下,
虽然通过查看产生的汇编发现是在try块里面调用了析构函数
[解决办法]
mark
[解决办法]
mark
[解决办法]
高深
[解决办法]
ding
------解决方案--------------------


学习.mark!
[解决办法]
awesome!
[解决办法]
ISO的高人出来了 :)
[解决办法]
第一题,
传过去的是值,将空间释放后,退出函数,而原来指针的指向因为是传值而没有没有发生变化,任然指向那个空间,只不过此时这个空间已经被释放。
故不会再去调用构造函数

//不知道对不对

第二题
前面可以理解,对最后那个异常不是很懂,还清高手指教

第三题
模板特化的问题。接触过的应该可以写出来

第四题
把delete运算符设为私有之后(被保护起来),析构时将找不到delete,故编译应该出错

////////////////
全都未经过测试
[解决办法]
第三题谁说下 !~!~ 通不过编译!~!~
[解决办法]
补充 VC6环境

**********************************************************************************
E:\Microsoft Visual Studio\MyProjects\abc\abc.cpp(29) : error C2989: '?$abc@P6A?AVtemplate-parameter-BAB@Vtemplate-parameter-BAC@@Z ' : template class has already been defined as a non-template class
E:\Microsoft Visual Studio\MyProjects\abc\abc.cpp(29) : error C2988: unrecognizable template declaration/definition
[解决办法]
lz什么时候公布答案呢?
[解决办法]
VC6对模板支持不好
[解决办法]
学习下 慢慢研究
[解决办法]
第一题和我说的一样,楼主继续说其他几题
[解决办法]
mark
[解决办法]
做了,但是只有第一个可以编译出结果,其他都出错。
[解决办法]

第一题还是不明白,难道delete pobj的话,class abc必需在delete语句前面给出完整的定义?在它后面就不行?调用函数的话不就可以在前面只是声明一下,在后面给出定义也行吗?
[解决办法]

哪位前辈指点一下我上面提的问题啊?!
[解决办法]
MARK
[解决办法]
经测试,全部不会,谢谢
[解决办法]
第二题在VS03会编译不过??我都好好的


第二题解释:Primer 3(第 641/1043 页)


假设调用全局操作符new()分配内存,如果在调用构造函数的时候抛出一个异常的时候,那么设计


者怎么确保new分配的内存被正确释放呢?//.....接下来自己看喽~~


顺便把new和delete在C++中的伪码形式给大家:


new的分配动作 : Screen *ptr=new Screen(10,20);
与下列语句等价:
//C++伪码
ptr=Screen::operator new( sizeof(Screen) );
Screen::Screen(ptr, 10, 20);
即,new表达式先调用该类的操作new()来分配存储区,然后再调用构造函数初始化该对象,如果new失败,则抛出bad_alloc类型的异常,并且不会调用构造函数用操作符delete()释放存储区的动作,


如:
delete ptr;
与下列语句等价格
//C++伪码
Screen::~Screen(ptr);
Screen::operator delete(ptr, sizeof(*ptr) );
即,delete表达式首先调用该对象的析构函数,然后再调用该类的操作符delete()释放存储区。如果ptr的值是0,则不会调用析构函数的操作符delete();

,则不会调用析构函数的操作符delete();

[解决办法]
to caicaijuaner(多泡泡CSDN) :
ISO就是这么规定的,这样的结果是unknown。
而且看vc反汇编的代码证明了这点,根本就没有调析构函数。

[解决办法]
mark
[解决办法]
晕哈 第一题在vc++6.0sp6中就同不过啊(怀疑是不是软件有问题):


abc.obj - 1 error(s), 2 warning(s)
D:\学习\VC++\abc\abc.cpp(5) : warning C4150: deletion of pointer to incomplete type 'abc '; no destructor called
D:\学习\VC++\abc\abc.cpp(1) : see declaration of 'abc '
D:\学习\VC++\abc\abc.cpp(12) : error C2065: 'printf ' : undeclared identifier
D:\学习\VC++\abc\abc.cpp(24) : warning C4508: 'main ' : function should return a value; 'void ' return type assumed

[解决办法]
我用MinGW编译第一题,编译出错
a.cpp: In function `void del(abc*) ':
a.cpp:4: `pobj ' has incomplete type
a.cpp:3: forward declaration of `struct abc '
a.cpp:23:2: warning: no newline at end of file
[解决办法]
学习...
看来楼主比较忙啊!
期待楼主的解答......
[解决办法]
恩,路过来看看 ~
[解决办法]
template <typename T, typename P>
class abc <T (*)(P)> {

<T (*)(P> 是什么意思?

热点排行