C++ 重载delete[]运算符以允许使用析构函数的可收缩类型数组
我们正在尝试重载delete[]运算符以实现 它可以很好地处理没有特定析构函数的数据类型 当数据类型具有指定的析构函数时,新的[]运算符需要额外的字节 你能帮我们回答这些问题吗 为什么新的[]运算符需要使用特定析构函数的数据类型的额外字节? 新[]运算符将始终请求这些字节,还是依赖于库? 是否可以知道数据类型是否具有带有if语句的特定析构函数? 当代码试图收缩B的数组时,应该抛出一个未处理的异常C++ 重载delete[]运算符以允许使用析构函数的可收缩类型数组,c++,operator-overloading,realloc,delete-operator,C++,Operator Overloading,Realloc,Delete Operator,我们正在尝试重载delete[]运算符以实现 它可以很好地处理没有特定析构函数的数据类型 当数据类型具有指定的析构函数时,新的[]运算符需要额外的字节 你能帮我们回答这些问题吗 为什么新的[]运算符需要使用特定析构函数的数据类型的额外字节? 新[]运算符将始终请求这些字节,还是依赖于库? 是否可以知道数据类型是否具有带有if语句的特定析构函数? 当代码试图收缩B的数组时,应该抛出一个未处理的异常 #include<cstdlib> #include<iostream> u
#include<cstdlib>
#include<iostream>
using namespace std;
void*operator new[](size_t s){
cout<<"Block size: "<<s<<endl;
return malloc(s);
}
void operator delete[](void*p){
free(p);
}
void operator delete[](void*p,size_t s){
//Is it possible to know if the data type has a specific destructor?
bool destructor=0;
if(destructor){
p=(char*)p-8,s+=8;
}
cout<<"New block size: "<<s<<endl;
if(realloc(p,s)!=p)throw 0;
}
struct A{
char a;
A():a(0){}
~A()=default;
};
struct B{
char b;
B():b(0){}
~B(){}
};
int main(){
unsigned S=10,s=4;
cout<<"Creating "<<S<<" A's"<<endl;
A*a=new A[S];
cout<<"Creating "<<S<<" B's"<<endl;
B*b=new B[S];
cout<<"Shrinking A to "<<s<<" elements"<<endl;
operator delete[](a,sizeof(A)*s);
cout<<"Shrinking B to "<<s<<" elements"<<endl;
operator delete[](b,sizeof(B)*s);
cout<<"Deleting A and B"<<endl;
delete[]b,delete[]a;
return 0;
}
有关答覆的问题:
这可能回答第1点和第2点
当使用运算符new创建新数组时,通常使用cookie
存储以记住分配的数组元素长度数,以便
它可以被正确地释放
具体而言:
No cookie is required if the array element `type T` has a trivial destructor.
这意味着:
因为结构A有一个简单的析构函数,所以它不需要
曲奇
因为结构B有一个特定的析构函数,所以它需要一个大小为sizeofsize_t字节的cookie,该cookie存储在数组左侧的中间位置。
参考资料:我认为新运营商需要的任何额外空间都是实现定义的,依赖它是一个坏主意。为什么在if语句中使用,运算符而不是{}?这不是通常的做法。运算符而不是if语句的{}。我不理解您:您发布的代码的预期行为是什么?如果您可以使用C++11,这可能会有所帮助@nocom throwimg异常是针对可恢复错误的。如果在没有警告的情况下移动了非平凡可复制类的内存,则这是一个不可恢复的错误。在这种情况下,您应该终止程序,而不是抛出。还要注意的是,您可能需要弄清楚对象发生了什么:现在我想,您的删除应该先销毁,所以realloc可能不重要。但这意味着你需要重建。