首页
社区
课程
招聘
[原创]一道极难的C++模板题目
发表于: 2007-12-4 16:26 10804

[原创]一道极难的C++模板题目

2007-12-4 16:26
10804

/*
        一道极难的C++模板题目
以下代码包括两个模板 Auto1 和 Auto2。它们功能相同,但参数稍有不同。Auto1已经能正常
工作。但 Auto2 在这一行编译通不过,
         ::new( (void*)p ) *T;
设法修改使其通过,并得到正确结果。注意不要把 Auto2 改成 Auto1。
        注:本程序可以VC6和VS2005运行
*/

#include <stdio.h>
#include <Windows.h>
#include <new>

class LZF
{
public:
        int num;
        LZF(): num(133)
        {
        }
};

template <class T>
class Auto1
{
        T* m_p;
public:
        T* Allocate(void)
        {
                PBYTE pnew = new BYTE[sizeof(T) + 10];
                T* p = (T*)pnew;
                if (p != NULL)
                {
                        ::new( (void*)p ) T;     // 调用Class的构造函数
                }
                m_p = p;
                return p;
        }
};

template <class T>
class Auto2
{
        T m_p;
public:
        T Allocate(void)
        {
                PBYTE pnew = new BYTE[sizeof(*m_p) + 10];
                T p = (T)pnew;
                if (p != NULL)
                {
                        ::new( (void*)p ) *T;//这里编译出错。如何调用Class的构造函数?
                }
                m_p = p;
                return p;
        }

};

void test1()
{
        Auto1<LZF> a;
        int ret = a.Allocate()->num;
        if (ret == 133)
        {
                printf("good %d\n",ret);               
        }
        else
        {
                printf("error");
        }
}
void test2()
{
        Auto2<LZF*> a;
        int ret = a.Allocate()->num;
        if (ret == 133)
        {
                printf("good %d\n",ret);               
        }
        else
        {
                printf("error");
        }
}
void main( void )
{       
        test1();
        test2();
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 424
活跃值: (1879)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
LTT都说难了,我只能占位了……
2007-12-4 20:39
0
雪    币: 297
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
3
不知道楼主到底想实现什么功能.

不过有几个明显的错误:
PBYTE pnew = new BYTE[sizeof(*m_p) + 10];
如果想编译过,改成:
PBYTE pnew = new BYTE[sizeof(m_p) + 10];

模板展开以及这个sizeof是在编译期间.而用指针解引用却肯定要在运行期.这里肯定编不过.因为编译器不知道sizeof中的类型是什么.

::new( (void*)p ) *T;//这里编译出错。如何调用Class的构造函数?
同样的道理,你试图用指针指向的类型去构造,这也是错误的.要么这里改成T要么你做一个Wrapper重新传一个参数进来.

另外感觉你好像在自己实现new.分配类的内存,调用构造函数...
2007-12-4 21:46
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
4
是在做不出来奥~T 是 Pointer type 怎么转换为  type哦? 实在想不出来~ 翻了一晚上的MSDN 未果
2007-12-4 23:34
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
5
这3个类的设计本身就存在问题。LZF对象空间的分配具有特殊,因而不应该在外部Auto1和Auto2中分配,应该在LZF内部重载运算符new来实现各种特殊的空间分配要求。这才是解决问题的根本方法。

对于当前问题,想不出来,应该属于无解吧。已知对象指针求对象类型,这个问题就相当于给你4个字节,让你求类型。没戏

如果非要这么做的话,考虑到代码这么实现是为了不产生临时对象,
稍微变通了下,实现同样效果:
增加LZF::xx()函数,把B中的"::new( (void*)p ) *T"修改为"p->xx();"
void LZF::xx()
{
   ::new((void*)this) LZF;
}
2007-12-5 00:11
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
6
lz 是想弄个自动管理内存的东西吧,第一种看起来就很舒服。
如果只是为了不产生临时对象,这样做好像更慢一点

按ls 的写法,涉及到的每个类都要增加一个xx 函数,这样的设计也不是很好,至于怎么从指针类型推导出原类型就不知道了
2007-12-5 01:27
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
7
,同意北极星的观点
2007-12-5 09:02
0
雪    币: 229
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习了     ..............
2007-12-5 09:23
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
9
合理的方法应该就如我上面的第一个观点,在LZF中重载new
xx函数确实不好
另外LZ的设计中还有个目标就是空间分配的大小可调"sizeof(*m_p) + 10"
2007-12-5 09:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
占位学习。。。。
2007-12-5 19:07
0
雪    币: 437
活跃值: (273)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
11
智能指针?

害死人了 自己想了一个小时 GOOLE了两三个小时 没进展
2007-12-5 19:34
0
雪    币: 229
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
这个是自己出的,还是什么的竞赛题?
2007-12-6 09:10
0
游客
登录 | 注册 方可回帖
返回
//