operator delete
在未由SL返回的非空指针上调用SL被视为未定义行为operator new
,如此处针对(1)和(2)所述:https : //en.cppreference.com/w/cpp/memory/ new / operator_delete
除非ptr是空指针或者是先前从
operator new(size_t)
or的标准库实现获得的指针,否则未定义此函数的标准库实现的行为operator new(size_t, std::nothrow_t)
。
因此,它也未定义行为混合的用途operator new
,operator delete
和operator new[]
,operator delete[]
。我无法在标准说明中找到任何内容,说明该内容是否也可以替换operator new
并且operator delete
可以调用用户的分配方法。举个例子:
void* operator new(std::size_t p_size)
{
void *ptr = UserImplementedAlloc(p_size);
return ptr;
}
void* operator new[](std::size_t p_size)
{
void *ptr = UserImplementedAlloc(p_size);
return ptr;
}
void operator delete(void* p_ptr)
{
UserImplementedFree(p_ptr);
}
void operator delete[](void* p_ptr)
{
UserImplementedFree(p_ptr);
}
以下内容不确定吗?假设UserImplementedAlloc
始终返回正确的地址,而不返回nullptr
。
struct Simple
{
explicit Simple(); //Allocates m_bytes
~Simple(); //Frees m_bytes
char * m_bytes;
};
/*Placement new is not replaced or overridden for these examples.*/
//Example A
{
//Allocates and invokes constructor
Simple* a = new Simple();
//Invokes destructor
a->~Simple();
//Deallocates
UserImplementedFree(static_cast<void*>(a));
}
//Example B
{
//Allocates
void* addr = UserImplementedAlloc(sizeof(Simple));
//Invokes constructor
Simple* b = new (addr) Simple();
//Invokes destructor and deallocates
delete b;
}
我不是在寻找关于这是否不好的方法的讲座,我只是在试图确定这是否是定义的行为。
这两个示例都是未定义的行为。现在,我花了时间浏览C ++ 17标准最终草案,我找到了我需要的证据。
关于operator new
:
分配功能-§6.7.4.1.2
如果请求成功,则返回的值应为不同于任何先前返回的值p1的非空指针值(7.11)p0,除非随后将该值p1传递给
operator delete
实例A我们称之为新表达,Simple* a = new Simple()
,在内部将调用适当的operator new
。我们operator delete
在致电时会绕过UserImplementedFree(static_cast<void*>(a))
。即使operator delete
将调用此函数并可能执行相同的取消分配,但要注意的是,对的任何后续调用operator new
现在都可能返回与所拥有地址匹配的指针a
。并且a
从未被传给operator delete
。因此,我们违反了上述规则。
delete-expression-第8.3.5.2节
... delete的操作数的值可以是空指针值,指向由先前的new表达式创建的非数组对象的指针或指向表示该对象基类的子对象(4.5)的指针(第13条)。如果不是,则行为是不确定的。在第二个替代方案(删除数组)中,删除操作数的值可以是空指针值,也可以是由先前数组new-expression产生的指针值。83如果不是,则行为未定义。
在示例B中,我们不addr
通过new-expression进行分配。然后,我们尝试使用delete-expression对其进行分配。违反了以上规则。
这些示例的主要特征是将构造与分配分离,以及将破坏与重新分配分离。该标准规定以下内容:
new-expression -§8.3.4.11
对于,,和的数组
char
,new表达式的结果与分配函数返回的地址之间的差应为大小不大于的任何对象类型的最严格基本对齐要求(6.11)的整数倍。正在创建的数组的大小。[注意:因为假定分配函数将指针返回到针对具有基本对齐方式的任何类型的对象而适当对齐的存储,所以这种对数组分配开销的约束允许将字符数组分配给其他类型的对象,稍后再将其放入其中。—尾注]unsigned char
std::byte
因此,定义的行为可能看起来像这样:
{
//Allocates bytes
char* bytes = new char[sizeof(Simple)];
//Invokes constructor
Simple* a = new ((void *)bytes) Simple();
//Invokes destructor
a->~Simple();
//Deallocates
delete[] bytes;
}
再一次,不一定是好的做法,而是明确的行为。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句