自定义NEW/DELETE,无参数模板函数 特化

id27145 2009-06-01 11:35:29
目的:为减少实际new/delete操作次数,类对象在使用完后,将其指针放入一个queue中,做为空闲对象,供下次使用

class CA;
std::queue<CA*> freeCA;
CA* allocateCA(){
CA* p = NULL;
if (freeCA.empty())
p = new CA;
else{
p = freeCA.front();
freeCA.pop();
}
return p;
} // 释放操作为将指针p放入freeCA中(freeCA.push(p);)

有多个类 class CA; class CB;....
要求分配的接口统一,类似 CA* pa = NEW(CA); CB* pb = NEW(CB); 而不能针对每个类型写一个allocateXXX()
目前做法:

// 定义一个模板函数NEW/DELETE
template <typename T>
T* NEW()
{
return new T;
}

template <typename T>
void DELETE(T* p)
{
if (NULL != p) delete p;
}
// 然后针对类型特化
template <>
CA* NEW<CA>() // NEW()没有参数, 再次对class CB 特化时出错,原因为两个NEW只有返回值不一样,不能overloaded
{
CA *p = NULL;
if (freeCA.empty())
p = new CA;
else{
p = freeCA.front();
freeCA.pop();
}
return p;
}

template <>
void DELETE<CA>(CA* p)
{
if (NULL == p) return;
if (freeCA.size() < MAX_CA){
p.~CA();
freeCA.push(p);
}
else
delete p;
}
// 最后定义宏NEW(x)
#define NEW(x) NEW<x>()
#define DELETE(x, p) DELETE<x>(p)


问题:
由于 模板函数NEW()没有参数,所以对类CA特化后,再对类CB特化时,提示两个NEW()只有返回值不同,不能重载
该如何解决?
对模板函数特化不熟悉,不知道特化能不能解决这个问题。如果不能,有没有什么方法可以解决呢?
...全文
302 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
id27145 2009-06-02
  • 打赏
  • 举报
回复
不是单独开发 就要考虑到他人的环境
采用折中办法
谢谢所有回帖者
结帖
ltc_mouse 2009-06-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 id27145 的回复:]
错误为
error C2556: 'class cb *__cdecl NEW(void)' : overloaded function differs only by return type from 'class ca *__cdecl NEW(void)'
不知道你是怎么写的能通过
[/Quote]
是VC6的问题吗? 我是在VS2003下编译~
我的写法跟你的差不多呀,调用时使用的是NEW宏~

编译器认为无法重载,是否可以变通下,增加一个不使用的参数,这么做:


template <typename T>
T* NEW(T *)
{
return new T;
}

std::queue<ca*> freeca;
const int MAX_CA = 10;
template <>
ca* NEW<ca>(ca *)
{
ca *p = NULL;
if (freeca.empty())
p = new ca;
else{
p = freeca.front();
freeca.pop();
}
return p;
}

std::queue<cb*> freecb;
const int MAX_CB = 10;
template <>
cb* NEW<cb>(cb *)
{
cb *p = NULL;
if (freecb.empty())
p = new cb;
else{
p = freecb.front();
freecb.pop();
}
return p;
}

// 最后定义宏NEW(x)
#define NEW(x) NEW<x>((x*)NULL)
woods2001 2009-06-01
  • 打赏
  • 举报
回复
mark~
id27145 2009-06-01
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 fengxuxing 的回复:]

class CA{};
class CB{};

template <class T>
void f(){}

template<>
void f<CA>(){}

template<>
void f<CB>(){}

int main(int argc, char* argv[])
{
return 0;
}

[/Quote]
我试了

int main(int argc, char* argv[])
{
f<CA>();
f<CB>();
return 0;
}

两个f都是调用f<CA>();
id27145 2009-06-01
  • 打赏
  • 举报
回复
to fengxuxing
目的确实是类似内存池,但时间水平有限,要实现一个正确的内存池要花点时间,想找个快速简单点的方法
to ltc_mouse
我的如下定义,VC6 F7时出错

template <typename T>
T* NEW()
{
return new T;
}

std::queue<ca*> freeca;
const int MAX_CA = 10;
template <>
ca* NEW<ca>()
{
ca *p = NULL;
if (freeca.empty())
p = new ca;
else{
p = freeca.front();
freeca.pop();
}
return p;
}

std::queue<cb*> freecb;
const int MAX_CB = 10;
template <>
cb* NEW<cb>()
{
cb *p = NULL;
if (freecb.empty())
p = new cb;
else{
p = freecb.front();
freecb.pop();
}
return p;
}

错误为
error C2556: 'class cb *__cdecl NEW(void)' : overloaded function differs only by return type from 'class ca *__cdecl NEW(void)'
不知道你是怎么写的能通过
Qlaiaqu 2009-06-01
  • 打赏
  • 举报
回复
SGI STL中的对象创建是分两边来进行的,
第一步,分配内存,直接使用包装好的函数分配内存(内部malloc实现)
第二步使用new((void*)MemoryPoint) ClassType(Parameter list);
对对象初始化
对象销毁
第一步:显示调用析构函数objectPoint-〉~ClassType();
第二步:将内存链接回内存池
上面的东西全部用模板实现
其实你要实现的东西就是stl里面的东西,我建议你看看sgi stl的内存池的部分代码就自然知道怎么弄了。
ltc_mouse 2009-06-01
  • 打赏
  • 举报
回复
lz试过对CB特化吗? 我试了下,可以特化,没有问题啊...
NEW<CA>() 与 NEW<CB>() 会调用不同的函数吧
id27145 2009-06-01
  • 打赏
  • 举报
回复
yt ls
试试看
qwprince2004 2009-06-01
  • 打赏
  • 举报
回复
可以把你需要的类型设置为摸板参数以实现重载

模板函数
template < typename {类型参数名称}, [ int {Name}=...][, ...] >
{函数定义}

模板类
template < typename ... , [ int {Name}=...] >
class ...

yshuise 2009-06-01
  • 打赏
  • 举报
回复
多研究一下 std::allocator
boost::allocator分配器就知道了。
先用malloc分配一个无类型的,然后用定位new构造对象。
内存管理是算法的问题。
Qlaiaqu 2009-06-01
  • 打赏
  • 举报
回复
可以这样特化阿,谁说不可以,就算CB是CA的继承类都可以特化

class CA{};
class CB{};

template <class T>
void f(){}

template<>
void f<CA>(){}

template<>
void f<CB>(){}

int main(int argc, char* argv[])
{
return 0;
}
id27145 2009-06-01
  • 打赏
  • 举报
回复
那么有没有办法实现这个设想呢,一个NEW()函数可以返回不同类型对象的指针
或者说模板函数 template <class T> T* NEW(){} 里能不能根据T的不同做不同处理
用typeid能实现吗?

现在做法是有一个类CAllocator,里面有针对各个类型的分配释放接口,allocateXXX/FreeXXX(XXX *p)
但被告之要统一接口,使用者不用调用allocateXXX,而是要能统一这个样子 XXX* p = NEW(XXX);
如何实现呢?
qizhao2001 2009-06-01
  • 打赏
  • 举报
回复
建议设计:对这些类重载new、delete操作,可以选用new的放置语法
lingyin55 2009-06-01
  • 打赏
  • 举报
回复
只有返回值不一样,肯定不能overloaded。

majun01 2009-06-01
  • 打赏
  • 举报
回复
mark
Qlaiaqu 2009-06-01
  • 打赏
  • 举报
回复
这个是编译器错误的问题,你现在如果真的要用这些代码,用一个错误的编译器去编译,到后面怎么办?这个错误会越放越大,最后是你的项目彻底失败,再说了,windows自己的编译器迁移并不需要太大的精力 。
id27145 2009-06-01
  • 打赏
  • 举报
回复
to fengxuxing
是 vc6 看来可能是编译器原因 不过要立即换也不现实 还是先采用其他折中的办法
Qlaiaqu 2009-06-01
  • 打赏
  • 举报
回复
换编译器吧...
Qlaiaqu 2009-06-01
  • 打赏
  • 举报
回复
#include <iostream>

using namespace std;

class CA{};
class CB{};

template <class T>
void f(){}

template<>
void f<CA>()
{
cout<<"A"<<endl;
}

template<>
void f<CB>()
{
cout<<"B"<<endl;
}

int main(int argc, char* argv[])
{
f<CA>();
f<CB>();
return 0;
}

我的答案是没有错的,我用的vs2008,不知道lz是什么编译器???vs6.0?

A
B
Press any key to continue . . .
id27145 2009-06-01
  • 打赏
  • 举报
回复
to ltc_mouse
恩 这个方法可行 不过看起来不是很好 虽然NEW宏不暴露出那个没用的参数
不过它的具体实现看起来就有点绕了 呵呵
再想想有没有更好的方法来处理这问题 前提是不自己去写完整的 强壮的内存池

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧