关于一道C++笔试题的纠结,学计算机的伤不起啊
今天,一个在美国读计算机研究生的哥们问了我一道笔试题,来自某金融巨头,我看完后很纠结,表示学计算机的伤不啊,出题不带这么业余的。
原题如下:
define class such that you can make object of this class on a heap but not on the stack.
大概意思是:
定义一个类,只能在堆上创建对象,而不能在栈上创建对象。
题目给出的答案是这样:
1 class A
2 {
3 private:
4 ~A();
5 public:
6 void Release()
7 {
8 delete this;
9 }
10 };
11
12 int main()
13 {
14 A a; // compile error
15 A* p = new A; // OK
16 p->Release();
17 }
2 {
3 private:
4 ~A();
5 public:
6 void Release()
7 {
8 delete this;
9 }
10 };
11
12 int main()
13 {
14 A a; // compile error
15 A* p = new A; // OK
16 p->Release();
17 }
意思是,把析构函数写成private,这样用A a;这种形式在栈上构造对象就会因为无法访问析构函数而报错
但是我想了下,这道题有问题,这种定义就能阻止在栈上创建对象了吗?在栈上创建对象不止这一种形式啊~
代码如下:
1 int main()
2 {
3 char buf[sizeof(A)];
4 new (buf) A();
5 A* p = (A*)buf;
6 }
2 {
3 char buf[sizeof(A)];
4 new (buf) A();
5 A* p = (A*)buf;
6 }
此时,p就是一个完整的A对象,没有任何问题,而且p是在栈上。
如果只是就题论题,到这里就结束了,因为上述的class A本本无法阻止我在栈上创建对象。
除非题目的make object仅仅是指 A a;这一种声明方式,那么。。当我以上都没说。。。
---------------------------------------------------------------------------------------
当然,上述这样的构造方式,问题也是显而易见的,即:没有调用析构函数,可能会导致内存泄露。
这一点不在题目的讨论范围内,但是也可以拿来说说,
第一种方法:
要改class A的定义,再加一个public的Destroy()函数,里面调用this->~A();这样就能通过调用p->Destroy()来析构了
第二种方法:
比较变态的方法。。。把class A的定义复制一份,改名为class B,里面的private换成public,然后
1 int main()
2 {
3 char buf[sizeof(A)];
4 new (buf) A();
5 A* pA = (A*)buf;
6 B* pB = (B*)pA;
7 pB->~B(); // 正确析构
8 }
2 {
3 char buf[sizeof(A)];
4 new (buf) A();
5 A* pA = (A*)buf;
6 B* pB = (B*)pA;
7 pB->~B(); // 正确析构
8 }
至此,纠结完毕,欢迎拍砖:D