以下是代码行:
A a = static_cast<A>(*(new A)); // ?
至少在64位铿锵声中编译好。
但实际分配的内存在哪里以及变量a会发生什么?
答案 0 :(得分:4)
除了不需要静态强制转换之外,分配有new A
的内存只是泄漏。您已经失去了对该指针的访问权限,并且永远不能delete
正确使用它。
但实际分配的内存在哪里以及变量a会发生什么?
变量a
会在像往常一样离开范围时被销毁。
答案 1 :(得分:2)
A a = static_cast<A>(*(new A)); // ?
这样做如下。
(new A) // allocate a new A on the heap
*(new A) // the type is now A instead of *A
static_cast<A>(*(new A)) // makes it into an type A from type A in an potentially unsafe way (here it is a no-op as they are the same type)
A a = static_cast<A>(*(new A)); // copies the (default) value of A to a
; // leaks the allocted A as the last reference to it disappear.
答案 2 :(得分:1)
我假设这行代码出现在一个函数中,我将回答这个问题。如果它出现在其他地方,关于&#34;堆栈&#34;是不准确的,但其他一切仍然准确。
这行代码编译为四个操作,我们可以将它们编写为自己的C ++行,以使事情更清晰。它在两个不同的地方进行两个分配,其中一个是&#34;泄露&#34;。
A a;
{
A *temp = new A;
a = *temp;
}
第一个操作为&#34;堆栈&#34;上的A
类型的对象分配空间,并对其进行默认初始化。可以通过变量a
访问此对象。它将在不迟于函数返回时自动销毁和释放;根据周围的上下文,这可能会更早发生,但在变量a
范围内的情况下都不会发生。
第二个操作为另一个类型为A
的对象分配空间,但是在&#34;堆&#34;而不是&#34;堆栈&#34;。此对象也是默认初始化的。 new
运算符返回指向此对象的指针,编译器将指针存储在临时变量中。 (我给该变量命名为temp
,因为我必须给它一些名称;在原始代码中,临时无法通过任何方式访问。)此对象只有在取消分配时才会被释放。 ,在将来的某个时刻,new
返回的指针用于delete
操作。
最后,第三个操作将temp
指向的堆上的对象的内容复制到堆栈中的对象上,可通过变量{{1}访问}。 (注意:您在此处撰写的a
无效,因为static_cast<A>(...)
已经有类型*temp
。因此,我将其删除了。)
最后,丢弃保存指向堆上对象的指针的临时变量。发生这种情况时,堆上的对象 不 解除分配;事实上,任何事情都无法解除分配。据说该对象有泄露。
你可能想写
A
在堆栈上分配一个对象而不执行任何其他操作,或者
A a;
它在堆上分配一个对象并安排引用计数它,以便它可能不会泄漏。 (你可能还有其他一些意思,但最有可能。)
答案 3 :(得分:1)
对于A
的简单定义,它等同于:
A a(*new(A));
在堆上动态分配A
,在堆栈上复制构造a
,并且泄漏动态分配。
对于A
的简单定义,总体效果可能是:
new A;
A a;
此副本实现了泄漏,没有浪费的复制操作或杂乱,冗余的演员:)