C++的一些试题

http://blog.csdn.net/wplxb/archive/2007/06/16/1654116.aspx 源文章地址


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

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

#include <stdio.h>

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. 写出下面程序的输出。

#include <stdio.h>
#include <stdlib.h>

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。

参考:
《More Effective C++》条款10: 在构造函数中防止资源泄漏
…… 不用为 BookEntry 中的非指针数据成员操心,在类的构造函数被调用之前数据成员就被自动地初始化。所以如果 BookEntry 构造函数体开始执行,对象的 theName、theAddress 和 thePhones 数据成员已经被完全构造好了。这些数据可以被看做是完全构造的对象,所以它们将被自动释放,不用你介入操作。……

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

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

#include <stdio.h>

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' 内置函数的时候就会报错了。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值