问题描述
就编译器优化而言,将堆分配更改为堆栈分配是否合法和/或可行?还是会破坏按规则?
As far as compiler optimizations go, is it legal and/or possible to change a heap allocation to a stack allocation? Or would that break the as-if rule?
例如,说这是代码的原始版本
For example, say this is the original version of the code
{
Foo* f = new Foo();
f->do_something();
delete f;
}
编译器可以将其更改为以下内容
Would a compiler be able to change this to the following
{
Foo f{};
f.do_something();
}
我不这么认为,因为如果原始版本依赖自定义分配器之类的东西,那将会产生影响.标准对此有何具体说明?
I wouldn't think so, because that would have implications if the original version was relying on things like custom allocators. Does the standard say anything specifically about this?
推荐答案
是的,这是合法的.C ++ 14的 expr.new/10
:
Yes, it's legal. expr.new/10
of C++14:
expr.delete/7
:
-如果分配调用对象的new表达式删除不遗漏,分配没有扩展(5.3.4),delete-expression应该调用一个释放函数(3.7.4.2).从new表达式的分配调用返回的值应该作为第一个参数传递给释放函数.
— If the allocation call for the new-expression for the object to be deleted was not omitted and the allocation was not extended (5.3.4), the delete-expression shall call a deallocation function (3.7.4.2). The value returned from the allocation call of the new-expression shall be passed as the first argument to the deallocation function.
-否则,如果分配已扩展或由以下人员提供扩展另一个新表达式的分配,并且由a产生的所有其他指针值的delete-expression由扩展提供存储的new表达式已评估new-expression,delete-expression应调用释放功能.从分配调用返回的值扩展的new-expression应该作为第一个参数传递给释放功能.
— Otherwise, if the allocation was extended or was provided by extending the allocation of another new- expression, and the delete-expression for every other pointer value produced by a new-expression that had storage provided by the extended new-expression has been evaluated, the delete-expression shall call a deallocation function. The value returned from the allocation call of the extended new-expression shall be passed as the first argument to the deallocation function.
-否则, delete-expression不会调用取消分配功能(3.7.4.2).
— Otherwise, the delete-expression will not call a deallocation function (3.7.4.2).
因此,总而言之,用定义的实现替换 new
和 delete
是合法的,例如使用堆栈而不是堆.
So, in summary, it's legal to replace new
and delete
with something implementation defined, like using the stack instead of heap.
注意:正如Massimiliano Janes所评论的那样,如果 do_something
抛出异常,则编译器将无法完全坚持此转换:编译器应在其中省略对 f
的析构函数调用.这种情况下(虽然在这种情况下,转换后的样本确实会调用析构函数).但是除此之外,可以自由地将 f
放入堆栈中.
Note: As Massimiliano Janes comments, the compiler could not stick exactly to this transformation for your sample, if do_something
throws: the compiler should omit destructor call of f
in this case (while your transformed sample does call the destructor in this case). But other than that, it is free to put f
into the stack.
这篇关于编译器可以优化从堆到栈的分配吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!