您的位置:首页 > 编程语言 > C语言/C++

四道稍微高级点的 C++ 试题

2012-04-05 21:49 190 查看
---------------------------------------------------------------------------

1. 写出下面程序的输出。

class abc;

void del(abc *pobj)

{

delete pobj;

}

class abc

{

public:

abc(){

printf("abc\r\n");

}

~abc(){

printf("~abc\r\n");

}

};

int main(int argc, char *argv[])

{

abc *pobj = new abc;

del(pobj);

}

答:abc

说明:定义 del 函数的时候,abc 的析构函数未定义,因此不会调用。

---------------------------------------------------------------------------

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(int argc, char * argv[])

{

try

{

new abc;

}

catch (int & i)

{

printf("%d\r\n", i);

}

return 0;

}

答:

malloc 1

abc

free

0

如果将“new abc;”换成“abc a;”,结果将是:

abc

0

说明:

1). 在 C++ 中,构造函数抛出异常后不会触发析构函数的调用,这和 object pascal 不一样。C++ 认为构造失败意味着对象没有产生,既然没有生就没有死。然而,当构造函数抛出异常时,仍会调用 delete 函数以释放内存。

operator new 重载全局 new,所以下面构造的时候 new 肯定会调用该 operator new。operator delete 同样。因此先输出 malloc 1。

new 分配完内存后,会自动调用构造函数,所以输出 abc。

在构造函数内部,抛出异常,throw int();

这个异常被捕获,输出 i,其值为 0。

但是在捕获的异常被处理之前,必须先释放内存。因为异常出错,但此时 new 分配内存的工作已经完成,如果不进行 delete 的话,势必会内存泄露。

2). 当生成堆栈对象时,C++ 自动调用的 operator new 和 operator delete 是全局的 operator new 和 operator delete。

---------------------------------------------------------------------------

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(int argc, char *argv[])

{

abc<void* (*)(int)> f_abc;

abc<int> i_abc;

}

答:

partial spec

member spec

说明:模板部分特化。

---------------------------------------------------------------------------

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

class a

{

public:

virtual ~a()

{

}

private:

void operator delete(void *p);

};

int main(int argc, char *argv[])

{

a _1;

}

答:不能

说明:

1) 如果一个类有虚析构函数的话,那么自定义 delete 函数必须有函数体。

2) 这个题目中,并不会调用 delete 函数。

3) 对于本题,delete 函数不被调用,但是编译器需要它,因此,不能没有定义。

参考:

如果对象是动态创建(也就是 new 出来的),那么在 delete 的时候系统会先调析构函数然后调 operator delete。编译器在编译的时候会把这 2 个步骤合并到一个函数里,看反汇编就知道了,函数名字类似 'scalar deleting destructor'。如果只是声明了 operator
delete 函数而没有定义,那么编译的时候会得不到函数地址,这样生成 'scalar deleting destructor' 内置函数的时候就会报错了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: