我认为这个问题可能重复,但我不知道如何搜索它。
我正在尝试重载operator new
,这样我可以在课后允许一个可变长度的缓冲区。我当前的设计是否按预期工作,还是未定义的行为?
如果答案在C ++ 98,C ++ 03和C ++ 11中有所不同,请解释其中的差异。
struct POD { /* ...other POD members here... */ };
struct BufferedPOD : POD
{
size_t n;
BufferedPOD()
// Assume n is already initialized...
{
}
static void *operator new(size_t size)
{
return ::operator new(size);
}
static void *operator new(size_t size, size_t additional_size)
{
void *const p = operator new(size + additional_size);
static_cast<BufferedPOD *>(p)->n = additional_size;
return p;
}
static void operator delete(void *p)
{
return ::operator delete(p);
}
static void operator delete(void *p, size_t)
{
return operator delete(p);
}
};
int main()
{
std::auto_ptr<BufferedPOD> p(new (1000) BufferedPOD());
foo(p.get()); // do something with buffer
return 0;
}
答案 0 :(得分:1)
首先,您依赖于未定义的行为,the memory is indeterminate upon calling the constructor。
在调试版本中,它通常会填充一些标记图案以便于调试。在版本构建中,这种自由通常只用于加速构造。
在两者中,读取不确定的对象会获得UB,但这将会详细说明。
无论如何,你的方式是错误的(让我们暂时忽略违反“三条法则”的行为:
只需声明::operator new
和::operator delete
的匹配重载,以及工厂函数(应该是唯一可以访问您可用的唯一代码的代码),它使用它并传递额外的 - 空间:
void* operator new(size_t a, size_t b) {
if(a+b< a || a+b < b)
throw new std::bad_alloc("::operator new(size_t, size_t) too big");
return operator new(a+b);
}
void operator delete(void* p, size_t a, size_t b) {return operator delete(p/*, a+b*/);}
struct Buffered : POD { // Not a pod due to inheritance
Buffered* make(size_t extra) {return new(extra) Buffered(extra);}
private:
size_t n;
Buffered(size_t extra) : n(extra) {}
Buffered(Buffered&) = delete;
void operator=(Buffered&) = delete;
};