编译器可以优化从堆到栈的分配吗? [英] Can the compiler optimize from heap to stack allocation?

查看:51
本文介绍了编译器可以优化从堆到栈的分配吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就编译器优化而言,将堆分配更改为堆栈分配是否合法和/或可行?还是会破坏按规则?

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:

允许实现忽略对可替换全局变量的调用分配函数(18.6.1.1,18.6.1.2).这样做时,存储而是由实施提供或通过扩展分配另一个新表达式.

An implementation is allowed to omit a call to a replaceable global allocation function (18.6.1.1, 18.6.1.2). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression.

expr.delete/7 :

如果delete-expression的操作数的值不为null指针值,然后:

If the value of the operand of the delete-expression is not a null pointer value, then:

-如果分配调用对象的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.

这篇关于编译器可以优化从堆到栈的分配吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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