2

我有以下代码,似乎用 new 创建一个引用是可以的,但是当涉及到用 new 创建一个对象时,当我尝试重新收集分配的内存时它会崩溃

float &f = *new float(1.3);
delete &f;
float f1 = *new float;
delete &f1;

想知道区别,谢谢!

4

2 回答 2

1

考虑:

float f1 = *new float;

它在免费存储上创建一个类型的对象,float然后将原始对象复制到f1. 您丢失了原始免费存储对象的地址,这会给您带来即时的内存泄漏。

所有内存解除分配函数都要求传递给它们的地址应该与内存分配函数返回的地址相同,因此当您调用未通过返回的地址时,最终会出现未定义的行为deletenew

请注意,未定义的行为并不要求崩溃,但没有崩溃并不意味着代码中没有问题。

于 2013-11-10T07:05:42.023 回答
0

首先,“使​​用新创建引用”并不是您正在做的事情。要理解这一点,需要分解代码......

new float(1.3);

这为浮点数分配了 4 个字节的内存,使用 1.3 double 常量构造浮点数,并返回指向内存开头的指针 - 4 个字节中的第一个。

*new float(1.3);

这“取消引用”了 new 运算符返回的指针,因此您不是读取指针值,而是读取它指向的 4 字节float数据。

float &f = *new float(1.3);

float使用new 提供的构造一个引用 f 。虽然(AFAIK)引用被实现为具有更大编译器优化潜力的指针(?),但这是人们抱怨的一部分。从概念上讲,引用浮点数,您不应该假设您可以检索地址、释放内存并因此在以后使引用无效。

但是,正如您所发现的,它确实有效,您可以检索地址......

&f

在引用的位置产生一个指向内存的指针,然后你可以

delete &f;

要回答您的实际问题...

float f1 = *new float;

可以改写如下

float f1; //a float on the stack!
f1 = *new float; //should probably be: *new float(1.3)

它不会初始化引用,而是将 new 分配的数据复制到堆栈上的浮点数。复制之后,返回的内存地址new就永远丢失了——你已经“泄露”了内存。

现在谈谈它为什么会崩溃。

&f1;

f1在堆栈上创建一个指向 float 的指针。该内存不是由newnew 最终使用的内存分配库创建或创建的。正在尝试释放内存分配库中不存在的内存地址...

delete &f1;

...导致你的崩溃。

和之间的区别:一个是引用,内部实现为指针(假定永远不会更改),另一个是在堆栈上声明的实际浮点变量,它不引用其他内存。float &ffloat f1

你应该做的是

float *f = new float(1.3f);
// access f as *f = 1.2f or cout << *f
delete f;
于 2013-11-11T06:35:29.393 回答