【问题标题】:Creating string array with overriden new[] operator使用覆盖 new[] 运算符创建字符串数组
【发布时间】:2023-03-29 18:45:01
【问题描述】:

我们和我的朋友一起做了一个程序,其中覆盖了 new 和 new[] 运算符。 我发现当我尝试使用此代码创建字符串数组时:

string* Test1 = new string[10];

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

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 Proffesional

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

【问题讨论】:

  • 你真的要分配一个由 10 个字符串组成的数组吗?
  • 是的,我就是这么做的
  • 当您尝试分配new string[10] 时,e 在重载的new[] 中有什么值?
  • new[] 中是 328,在非覆盖 new[] 中是 408

标签: c++ string overriding new-operator


【解决方案1】:

答案是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_type 更改为 std::vector&lt;int&gt;,我们有

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 - 它可以正常工作)

【讨论】:

    猜你喜欢
    • 2021-06-26
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2013-05-08
    相关资源
    最近更新 更多