由重载的new返回的指针被更改

时间:2017-07-25 17:10:59

标签: c++

我遇到了一个奇怪的问题,我创建了这个简单的程序来演示它。我知道代码本身没有多大意义,但我想突出一些我不理解的东西。

#include <iostream>
using namespace std;

class tempClass{
public:
    float n;
    tempClass(){};
    ~tempClass(){} //VERY IMPORTANT LINE
    void* operator new[](size_t size);
};


void* tempClass::operator new[](size_t size){
    tempClass* a;
    a= ::new tempClass[2];
    for (int i = 0; i < 2; i++)
    {
        a[i].n = i*10;
    }
    cout << a << endl;
    return a;
}


int main(){
    tempClass* a;
    a = new tempClass[2];
    cout << a << endl;
    cout << a[0].n << endl;
    return 0;
}

在代码中,我已经为我创建的类重载了operator new。但是,函数的行为会发生变化,具体取决于我是否包含类的析构函数。我注意到,如果我不包含析构函数,一切正常,而如果我这样做,指针a的返回值将始终增加8。因此,在此示例中,如果我包含析构函数,则程序的最后cout将打印20,如果不包含析构函数,则0将打印Function TrimTrailingZeroes(BigNumber As String) As String Dim i As Integer For i = Len(BigNumber) To 1 Step -1 If Mid(BigNumber, i, 1) <> "0" Then TrimTrailingZeroes = Left(BigNumber, i) Exit Function End If Next i TrimTrailingZeroes = BigNumber End Function 。为什么会这样?

2 个答案:

答案 0 :(得分:4)

Array-new-expressions将未指定数量的开销传递给分配函数(即您的operator new重载)。这是为了允许实现记录数组元素的数量,以便在删除时调用析构函数。

如果您的实现检测到类没有需要析构函数被调用(因为它可以轻易破坏),它可能会选择不需要相同数量的开销

正式措辞是8.3.4 [expr.new] p11:

  

new-expression 调用分配函数并且该分配尚未扩展时, new-   表达式将请求的空间量作为类型的第一个参数传递给分配函数   std::size_t该参数不得小于正在创建的对象的大小;它可能更大   仅当对象是数组时才创建对象的大小。 [...]

请注意,开销是未指定的,因此原则上每次调用都可能有所不同! (这也是placement-array-new is unusable的原因。)但是,许多实现使用的Itanium ABI在&#34; array cookie&#34;工作,并与您的经验相匹配。

答案 1 :(得分:2)

这是Itanium CXX ABI array operator new[] cookie

  

当operator new用于创建新数组时,通常会存储cookie以记住分配的长度(数组元素的数量),以便可以正确地释放它。 [...]   
  如果数组元素类型T有一个简单的析构函数(12.4 [class.dtor]) [...]

,则不需要cookie

析构函数(除了在类中定义为= default之外的析构函数)是非平凡的。