c++ - 使用覆盖 new[] 运算符创建字符串数组

标签 c++ string overriding new-operator

和我的 friend 一起,我们制作了一个带有重写 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变成 0x0000000009dfaa98。
这种情况仅发生在字符串类型上。我尝试对“int[10]”、“string* [10]”和我的一个类的对象执行相同的操作,但仅在处理字符串时才会出现问题,代码也是:

string* Test1 = new string;

工作得很好。

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

PS:我们使用的是 Visual Studio 2012 Professional

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

最佳答案

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

这是测试该问题的示例代码(您可以更改 tested_type 的 typedef 值):

#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_typestd::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 - 它确实有效)

关于c++ - 使用覆盖 new[] 运算符创建字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18370083/

相关文章:

c++ - 我如何使用RPM从内存中读取std::string

c++ - wstring 到 LPCWSTR 不使用 c_str()

java - BufferedWriter 没有在文件中为添加了 "\n"的字符串写入新行

python - 将字符串拆分为相同字母的 block

ios - 使用 arc 和 dynamic 属性覆盖 setter

c++ - 无法解决使用 Ubuntu 构建 C++ 时的声明和循环错误

c++ - 调用 join 后删除 std::thread?

python - 需要更优雅的解决方案来均匀字符串长度

java - SCJP - 使用异常处理的重写方法会引发编译器错误

ASP.NEt WebForms UserControl : Why is overriding . 可见导致 System.StackOverflowException?