使用重写的 new[] 运算符创建字符串数组 [英] Creating string array with overriden new[] operator

查看:75
本文介绍了使用重写的 new[] 运算符创建字符串数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

With my friend we made a program with overriden new and new[] operators. I discovered that when I try to create string array with this code:

string* Test1 = new string[10];

函数返回无效指针(通常它的值向前移动 8 位,我正在将程序编译到 x64 平台).我们的 new[] 函数看起来像这样:

Function returns invalid pointer (Usually it's value is moved 8 bits foreward, I'm compilling program to x64 platform). Our new[] function looks like that:

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

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

when running program with debugger before return, pointer Test2 had value 0x0000000009dfaa90, but value of Test1 became 0x0000000009dfaa98.
This situation happens only with string type. I've tried do the same with "int[10]", "string* [10]" and object of one of my classes but problem occures only when dealing with string, also, code:

string* Test1 = new string;

工作得很好.

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

Could someone explain me why it's happenning and how to make it works correctly?

PS:我们使用的是 Visual Studio 2012 专业版

PS: We are using Visual Studio 2012 Proffesional

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

I just tested it non-overriden new[] and it's working this same way when creating string table (Returned pointer is other than the one that function try to return), so it seems to not be a problem. Could someone explain me why value of pointer changes only for string arrays, and how it changes if there seems to not be any other instruction that could change it?

推荐答案

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

The answer is that new/delete and new[]/delete[] are different. It may not come as a surprise to you, but the other surprising news (pun not intended) is that new operator and operator new are different.

以下是测试问题的示例代码(您可以更改 tested_type 的类型定义):

Here's an sample code testing the issue (you can change what tested_type is typedef'd to):

#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 位编译器)

(Note - I have a 32-bit compiler)

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

If we change tested_type to int, we have:

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,我们有

Now, if we change tested_type to std::vector<int>, we have

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

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

Now we see a pattern here: the extra bytes added are equal to the number of elements allocated. Also, the only time where the bytes are added, is when the type is non-trivial...

就是这样!

调整地址的原因是new[]要存储元素个数.之所以需要在某些情况下存储元素的数量,而在其他情况下不需要,是因为 delete[] 调用了析构函数,而 delete[](但不是delete 只为单个元素调用析构函数)必须以某种方式知道它必须销毁多少个元素.不需要为像 int 这样的基本类型调用析构函数,所以 new[] 不存储有多少.

The reason why the address is adjusted is that new[] wants to store number of elements. And the reason why we need to store the number of elements in some cases, but not in others, is because delete[] calls destructors, and delete[] (but not delete which just calls destructor for a single element) must somehow know how many elements it must destroy. There is no need for calling destructors for basic types like int, and so new[] doesn't store how many there are.

(另外,我推荐 std::vector - 它只是有效)

(also, I recommend std::vector - it just works)

这篇关于使用重写的 new[] 运算符创建字符串数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆