结构体new重载有关问题

结构体new重载问题
typedef struct tagMemoryBlock
{
unsigned int uiSize;
unsigned short usFree;
unsigned short usFirst;
tagMemoryBlock *pNext;
char aData[1];
static void* operator new(unsigned int, unsigned short usNum, unsigned short usUnitSize)//为什么第一个参数只有声明了类型而没有实际的参数???
{
return ::operator new(sizeof(tagMemoryBlock) + (usNum * usUnitSize));
}

static void operator delete(void* p, unsigned int)
{
::operator delete(p);
}
tagMemoryBlock(unsigned short usNum, unsigned short usUnitSize)
{
uiSize = (unsigned int)(usNum * usUnitSize);
usFree = usNum;
usFirst = 0;
pNext = 0;

char *pData = aData;
for (int i = 1; i < usNum; ++ i)
{
*((unsigned short *)pData) = i;
pData += usUnitSize;
}
}
~tagMemoryBlock()
{

}
}MemoryBlock, *PMemoryBlock;


pMemoryBlock = new (m_uiGrowNum, m_uiUnitSize) MemoryBlock(m_uiGrowNum, m_uiUnitSize);//这个new 的格式不明白,MemoryBlock(m_uiGrowNum, m_uiUnitSize);这个是结构体的构造函数,这应该是对前面new的结构体初始化,但是new后面只有两个参数,而结构体中的new声明的是3个参数。这个有点不明白,请各位不吝赐教!

------解决方案--------------------
第一个参数是默认传递的。
------解决方案--------------------
重载 operator new
 
opeator new 的重载和其它操作符大不相同.即使你不重载, 默认的 operator new 也可施用于你的自定义型别上(operator, 也具有此特性), 而其它操作符如果不进行重载就无法使用. 其次, 其它重载其它操作符时参数个数都是固定的, 而 operator new 的参数个数是可以任意的, 只需要保证第一个参数为 size_t, 返回类型为 void * 即可, 而且其重载的参数类型也不必包含自定义类型. 更一般的说, operator new 的重载更像是一个函数的重载, 而不是一个操作符的重载.

------解决方案--------------------
作为c++标准控,我用c++标准回答你。

1. new的语法

我们最常见的就是 new Type; 其中Type可以是int, double或者用户自定义类型。

new也可以这样用(这种用法叫做placement new),

new (expression-list) Type;

其中expression-list就是一个逗号分开的表达式,例如 new (a, b, c) Type。有什么特殊意义呢?

见下面的例子:

— new T 会调用函数 operator new(sizeof(T)),
— new(2,f) T 会调用函数 operator new(sizeof(T),2,f)


sizeof(T)是T的大小,永远作为operator new的第一个参数。标准原文:A new-expression passes the amount of space requested to the allocation function as the first argument of
type std::size_t. That argument shall be no less than the size of the object being created;

实际上就是把(2,f)放到operator new 第二个参数往后推。

为什么这样做呢?因为operator new是一个函数,而我们却不用普通的方法调用该函数,为了能够传递更多的参数,就想出了这么个不伦不类的语法。那你说为什么不这样呢?

new T(2,f)

答案很明显,因为这样(2,f)会被当成T的constructor的参数。

其实new的全写是: new (expression-list)_optional Type (constructor arguments)_optional

_optional是可有可无的意思。

2. 你的问题:

static void* operator new(unsigned int, unsigned short usNum, unsigned short usUnitSize)//为什么第一个参数只有声明了类型而没有实际的参数???
{
return ::operator new(sizeof(tagMemoryBlock) + (usNum * usUnitSize));
}

第一个unsigned int其实应该是std::size_t。编译器会传递该类型的大小(sizeof(tagMemoryBlock))。

但是很明显该函数的实现忽略了该大小,而是直接用了sizeof(tagMemoryBlock)。其实他也可以直接利用第一个参数而不用sizeof().

pMemoryBlock = new (m_uiGrowNum, m_uiUnitSize) MemoryBlock(m_uiGrowNum, m_uiUnitSize);

就相当于调用 operator new(sizeof(tagMemoryBlock), m_uiGrowNum, m_uiUnitSize)
然后再调用constructor tagMemoryBlock(m_uiGrowNum, m_uiUnitSize)


------解决方案--------------------
“//为什么第一个参数只有声明了类型而没有实际的参数???”
这个是标准规定必须有第一个这样的参数;

另外,3楼说的很好。

pMemoryBlock = new (m_uiGrowNum, m_uiUnitSize) MemoryBlock(m_uiGrowNum, m_uiUnitSize);

中"new (m_uiGrowNum, m_uiUnitSize)"表示按照你自定义的new申请内存方式申请了内存;
后面的"MemoryBlock(m_uiGrowNum, m_uiUnitSize)"表示在刚刚申请的内存上构造这个对象。

具体new的用法,可参考下面的这个地址,讲的很好:
http://www.360doc.com/content/10/0416/15/1066294_23344701.shtml


------解决方案--------------------