四道稍微高级点的 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' 内置函数的时候就会报错了。
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' 内置函数的时候就会报错了。
相关文章推荐
- C/C++面试题四(稍微高级)
- 4道稍微高级点的c++面试题,供初学者一窥门径
- C/C++面试题四(稍微高级)
- 我出的C++试题
- C++继承体系高级话题
- [C++] gdb高级调试方法
- C++随笔分类列表(高级)
- 如何成为一个C++高级程序员
- 一些C++试题
- c++高级---C++类构造函数初始化列表以及对象成员的构造
- 左神第七讲-代码C++实现(后四道题)
- 2013第四届蓝桥杯预赛试题本科c++第39级台阶
- 软件设计师2005年11月下午试题5(C++ 观察者模式)
- 猎头职位 软件平台开发高级工程师 c++
- 【面试笔试-c/c++】人民搜索2012校园招聘试题
- 1992年高级程序员下午试题2(数字排列)
- 从两道经典试题谈C/C++中联合体(union)的使用
- 关于XML一些稍微高级点的技术
- (转)C/C++ 程序设计员应聘常见面试试题深入剖析
- 历届蓝桥杯C/C++省赛试题