重载运算符 new[] 的行为取决于析构函数
Behavior of overloaded operator new[] depends on destructor
以下代码片段重载 operator new[]
并打印出 size
所需的地址和指针地址
class MyClass
{
private:
int _data; //sizeof(MyClass) == 4
public:
void* operator new[](size_t size)
{
cout << "MyClass::operator new[]" << endl;
cout << "size = " << size << endl;
void* p = malloc(size);
cout << "p = " << p << endl;
return p;
}
};
int main()
{
MyClass* a = new MyClass[100];
cout << "a = " << a << endl;
}
输出
>> MyClass::operator new[]
>> size = 400
>> p = 0x55e335a3f280
>> a = 0x55e335a3f280
但是,通过显式 adding/defining 析构函数
class MyClass
{
...
public:
...
~MyClass() {}
};
int main()
{
MyClass* a = new MyClass[100];
cout << "a = " << a << endl;
}
结果变了
>> MyClass::operator new[]
>> size = 408
>> p = 0x564f30cd7280
>> a = 0x564f30cd7288
表示表达式 new[]
正在向 operator new[]
请求额外的 8 字节内存。多出的内存字节好像是存放数组大小的,甚至可以访问!
cout << "info: " << *(reinterpret_cast<size_t*>(a) - 1) << endl;
结果
>> info: 100
我的问题是谁以及为什么使用这 8 字节的信息?这是标准的一部分吗?如果是这样,是否可以解释为什么它被设计成这样?
unspecified调用任何数组时是否有开销,开销有多大new
。这种行为完全在提供给编译器的宽大处理范围内。额外的 space 通常用于指示数组中有多少个元素。
调用delete[]
时,需要调用每个元素的析构函数;这只有在我们知道有多少元素的情况下才能做到。在元素具有普通析构函数的情况下,需要调用其中 none 个,因此不需要 space。
请注意,尽管实现通常在 operator delete
中委托给 std::free
,但不能保证如此,您也应该重载 operator delete
。
如果您添加一个具有非平凡析构函数的成员而不是析构函数,您应该会看到类似的行为,例如 std::string
.
当你有一个析构函数时,运行时需要知道有多少元素,以便它可以在销毁数组之前销毁它们。
该标准并未指定应如何实现这些,但在实际数据之前存储元数据简单、方便且高效。
以下代码片段重载 operator new[]
并打印出 size
所需的地址和指针地址
class MyClass
{
private:
int _data; //sizeof(MyClass) == 4
public:
void* operator new[](size_t size)
{
cout << "MyClass::operator new[]" << endl;
cout << "size = " << size << endl;
void* p = malloc(size);
cout << "p = " << p << endl;
return p;
}
};
int main()
{
MyClass* a = new MyClass[100];
cout << "a = " << a << endl;
}
输出
>> MyClass::operator new[]
>> size = 400
>> p = 0x55e335a3f280
>> a = 0x55e335a3f280
但是,通过显式 adding/defining 析构函数
class MyClass
{
...
public:
...
~MyClass() {}
};
int main()
{
MyClass* a = new MyClass[100];
cout << "a = " << a << endl;
}
结果变了
>> MyClass::operator new[]
>> size = 408
>> p = 0x564f30cd7280
>> a = 0x564f30cd7288
表示表达式 new[]
正在向 operator new[]
请求额外的 8 字节内存。多出的内存字节好像是存放数组大小的,甚至可以访问!
cout << "info: " << *(reinterpret_cast<size_t*>(a) - 1) << endl;
结果
>> info: 100
我的问题是谁以及为什么使用这 8 字节的信息?这是标准的一部分吗?如果是这样,是否可以解释为什么它被设计成这样?
unspecified调用任何数组时是否有开销,开销有多大new
。这种行为完全在提供给编译器的宽大处理范围内。额外的 space 通常用于指示数组中有多少个元素。
调用delete[]
时,需要调用每个元素的析构函数;这只有在我们知道有多少元素的情况下才能做到。在元素具有普通析构函数的情况下,需要调用其中 none 个,因此不需要 space。
请注意,尽管实现通常在 operator delete
中委托给 std::free
,但不能保证如此,您也应该重载 operator delete
。
如果您添加一个具有非平凡析构函数的成员而不是析构函数,您应该会看到类似的行为,例如 std::string
.
当你有一个析构函数时,运行时需要知道有多少元素,以便它可以在销毁数组之前销毁它们。
该标准并未指定应如何实现这些,但在实际数据之前存储元数据简单、方便且高效。