正在使用overriden new[]运算符创建字符串数组

Creating string array with overriden new[] operator

本文关键字:运算符 创建 字符串 数组 new overriden      更新时间:2023-10-16

和我的朋友一起,我们用overriden new和new[]运算符制作了一个程序。当我尝试用以下代码创建字符串数组时,我发现:

string* Test1 = new string[10];

函数返回无效指针(通常它的值向前移动8位,我正在将程序编译到x64平台)。我们的新[]功能如下:

void* operator new[] (size_t e)
{
    void* Test2 = operator new(e); 
    return Test2;
}

在返回之前使用调试器运行程序时,指针Test2的值为0x0000000009dfaa90,但Test1的值变为0x0000000009 dfaa98。
这种情况只发生在字符串类型中。我试过对"int[10]"、"string*[10]"和我的一个类的对象做同样的操作,但问题只发生在处理字符串时,还有代码:

string* Test1 = new string;

工作非常好。

有人能解释一下为什么会发生这种情况,以及如何使其正确工作吗?

PS:我们正在使用Visual Studio 2012专业版

编辑:我刚刚测试了它的非覆盖new[],它在创建字符串表时也以同样的方式工作(返回的指针不是函数尝试return的指针),所以这似乎不是问题。有人能解释一下为什么指针的值只对字符串数组发生变化,以及若并没有任何其他指令可以改变它,指针的值是如何变化的吗?

答案是new/deletenew[]/delete[]不同。这可能不会让你感到惊讶,但另一个令人惊讶的消息(双关语并非有意)是new运算符和operator new不同。

以下是测试该问题的示例代码(您可以将tested_type的typedef'd更改为):

#include <iostream>
#include <vector>
#include <string>
typedef std::string tested_type;
void* Test2;
size_t allocated_mem_size;
void* operator new[] (size_t e)
{
    void* retaddr = operator new(e);
    Test2 = retaddr;
    allocated_mem_size = e;
    return retaddr;
}
int _tmain(int argc, _TCHAR* argv[])
{
    void* Test1 = new tested_type[10];
    std::cout << "sizeof(tested_type)*10 is " << sizeof(tested_type)*10 << "n"
              << "Test1 is " << Test1 << "n"
              << "Test2 is " << Test2 << "n"
              << "operator new[] was called with e == " << allocated_mem_size << "n"
              << "What's in the missing bytes? " << *(size_t*)Test2 << "n";
}

我机器上的输出是:

sizeof(tested_type)*10 is 280
Test1 is 0085D64C
Test2 is 0085D648
operator new[] was called with e == 284
What's in the missing bytes? 10

(注意-我有一个32位编译器)

如果我们将tested_type更改为int,则我们有:

sizeof(tested_type)*10 is 40
Test1 is 0070D648
Test2 is 0070D648
operator new[] was called with e == 40
What's in the missing bytes? 3452816845

现在,如果我们将tested_type更改为std::vector<int>,我们就有

sizeof(tested_type)*10 is 160
Test1 is 004AD64C
Test2 is 004AD648
operator new[] was called with e == 164
What's in the missing bytes? 10

现在我们在这里看到一个模式:添加的额外字节等于分配的元素数量。此外,添加字节的唯一时间是当类型不是平凡的时候。。。

就是这样!

调整地址的原因是new[]想要存储元素的数量。在某些情况下,我们需要存储元素的数量,而在其他情况下则不需要,这是因为delete[]调用析构函数,而delete[](而不是delete,它只调用单个元素的析构函数)必须知道它必须销毁多少元素。对于像int这样的基本类型,不需要调用析构函数,因此new[]不存储析构函数的数量。

(另外,我推荐std::vector-它只是起作用)