好吧,我想我们都同意以下代码所发生的事情是未定义的,具体取决于传递的内容,
void deleteForMe(int* pointer)
{
delete[] pointer;
}
Run Code Online (Sandbox Code Playgroud)
指针可以是各种不同的东西,因此delete[]对它执行无条件是未定义的.但是,让我们假设我们确实传递了一个数组指针,
int main()
{
int* arr = new int[5];
deleteForMe(arr);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,在这种情况下,指针是一个数组,谁知道这个?我的意思是,从语言/编译器的角度来看,它不知道arr数组指针是否指向单个int的指针.哎呀,它甚至不知道是否arr是动态创建的.但是,如果我做以下事情,
int main()
{
int* num = new int(1);
deleteForMe(num);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
操作系统足够聪明,只能删除一个int,而不是通过删除超出该点的其余内存来进行某种类型的"杀戮狂欢"(与strlen非\0终结字符串形成对比- 它将一直持续到它点击0).
那么他们的工作是记住这些东西吗?操作系统是否在后台保留某种类型的记录?(我的意思是,我意识到我开始这篇文章时说过发生的事情是未定义的,但事实是,'杀戮狂欢'的情况不会发生,所以因此在实际世界中有人记得.)
这个问题的灵感来自一个类似的问题:delete []"如何"知道操作数数组的大小?
我的问题有点不同: 有没有办法以编程方式确定C++数组的大小?如果没有,为什么? 我看到的每个接受数组的函数也需要一个整数参数来赋予它大小.但正如链接问题指出的那样,delete[]必须知道要释放的内存大小.
考虑这个C++代码:
int* arr = new int[256];
printf("Size of arr: %d\n", sizeof(arr));
Run Code Online (Sandbox Code Playgroud)
这打印" Size of arr: 4",这只是指针的大小.有一些打印256的函数会很好,但我不认为C++中存在一个函数.(同样,问题的一部分是为什么它不存在.)
澄清:我知道如果我在堆栈上声明数组而不是堆(即" int arr[256];"),则sizeof运算符将返回1024(数组长度*sizeof(int)).
我知道在C++中无法获得动态创建的数组的大小,例如:
int* a;
a = new int[n];
Run Code Online (Sandbox Code Playgroud)
我想知道的是:为什么?人们是否在C++规范中忘记了这一点,还是有技术原因?
信息不是存储在某个地方吗?毕竟,命令
delete[] a;
Run Code Online (Sandbox Code Playgroud)
似乎知道它必须释放多少内存,所以在我看来,delete[]有一些方法可以知道它的大小a.
从什么是写在这里,new分配在自由存储,同时malloc采用堆和这两个术语往往意味着同样的事情.
根据此处的内容,realloc可以将内存块移动到新位置.如果免费存储和堆是两个不同的内存空间,它是否意味着任何问题呢?
具体来说,我想知道它是否安全使用
int* data = new int[3];
// ...
int* mydata = (int*)realloc(data,6*sizeof(int));
Run Code Online (Sandbox Code Playgroud)
如果没有,是否还有其他方式可以安全地realloc分配内存new?我可以分配新的区域和memcpy内容,但据我所知,realloc如果可能的话可以使用相同的区域.
我想知道delete操作符如何在给出与对象的真实内存位置不同的基类指针时计算出需要释放的内存位置.
我想在我自己的自定义分配器/解除分配器中复制此行为.
考虑以下层次结构:
struct A
{
unsigned a;
virtual ~A() { }
};
struct B
{
unsigned b;
virtual ~B() { }
};
struct C : public A, public B
{
unsigned c;
};
Run Code Online (Sandbox Code Playgroud)
我想分配一个C类型的对象,并通过类型B的指针删除它.据我所知,这是一个有效的使用operator delete,它在Linux/GCC下工作:
C* c = new C;
B* b = c;
delete b;
Run Code Online (Sandbox Code Playgroud)
有趣的是,指针'b'和'c'实际上指向不同的地址,因为对象在内存中的布局方式,而删除操作符"知道"如何查找和释放正确的内存位置.
我知道,一般来说,在给定基类指针的情况下找不到多态对象的大小是不可能的:找出多态对象的大小.我怀疑通常不可能找到对象的真实内存位置.
笔记:
我很好奇delete []如何计算分配内存的大小.当我做的事情:
int* table = new int[5];
delete[] table;
Run Code Online (Sandbox Code Playgroud)
我明白表的内存是释放的.但是,如果我将指针重新分配给某个不同的表,会发生什么.
int* table = new [5];
int* table2 = new [9];
table = table2;
delete[] table;
Run Code Online (Sandbox Code Playgroud)
我可以免费使用5或9号桌子吗?我对new []和delete []如何共享有关其大小的信息感兴趣.或许我错过了一些必不可少的东西.
我试图在运行时确定对象的大小.sizeof不起作用,因为它在编译时返回大小.这是我的意思的一个例子:
class Foo
{
public:
Foo()
{
c = new char[1024*1024*1024];
}
~Foo()
{
delete[] c;
}
private:
char *c;
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,sizeof(Foo)将是4个字节而不是〜1GB.如何在运行时确定Foo的大小?提前致谢.
当我在C++(T * p = new T[n])中分配动态数组时,我使用delete [] p释放分配的内存.显然,系统知道数组大小(按顺序调用n次T的析构函数).这在其他地方讨论过.例如,delete []"知道"操作数数组的大小是多少?.这是实施细节.
但为什么不决定提供这些信息呢?
谢谢
这是我一直想知道的事情,从来没有找到答案:
为什么当你在堆上分配一些东西时,你无法仅通过指针来确定它的大小,但是你可以仅使用指针来删除它,不知何故C++知道要释放多少字节?
这与它在堆上的存储方式有关吗?这些信息是否存在但C++没有公开?
也许这应该是一个单独的问题,但我认为它非常相关所以我会在这里问:
为什么必须使用delete []简单的delete命令来删除动态的元素数组; 为什么C++需要这些额外的信息才能正确释放所有内存?
所以,我已经用 C++ 开发了一些应用程序,所以我在 C++ 世界中并不是那么陌生,但我无法弄清楚为什么我们无法在 C++ 中找到动态分配数组的大小。
特别是,查看文档,如果我写:
delete[] array;
Run Code Online (Sandbox Code Playgroud)
它将删除数组中的所有元素(分配在堆上)......现在,为了删除它,必须在内存上写一些东西来告诉解除分配器“该数组有多少字节组成”......和那么问题来了,为什么我们也不能获得这些信息?