【问题标题】:Compilers evaluating constant expressions编译器评估常量表达式
【发布时间】:2016-02-25 16:48:55
【问题描述】:

我希望我的编译器(VS 2013)避免任何多余的算术计算,最好在编译时计算一次。

基本上我看到以下三种情况:

例如:

void Mesh::Draw1()
{
    const static uint32_t gStaticOffset = 0;
    const static uint32_t gVertexSize = sizeof(float) * 3;
    const static uint32_t gBoneIndexSize = sizeof(uint32_t) * MAX_BONES;
    const static uint32_t gBoneWeightSize = sizeof(float) * MAX_BONES;

    ...
}

void Mesh::Draw2()
{
    const uint32_t staticOffset = 0;
    const uint32_t vertexSize = sizeof(float) * 3;
    const uint32_t boneIndexSize = sizeof(uint32_t) * MAX_BONES;
    const uint32_t boneWeightSize = sizeof(float) * MAX_BONES;

    ...
}

const static uint32_t gStaticOffset = 0;
const static uint32_t gVertexSize = sizeof(float) * 3;
const static uint32_t gBoneIndexSize = sizeof(uint32_t) * MAX_BONES;
const static uint32_t gBoneWeightSize = sizeof(float) * MAX_BONES;

void Mesh::Draw3()
{
    ...  
}

个人想法,如有错误请指正:

  • Draw1() 可能会重新计算每个函数调用的局部表达式 取决于编译器
  • Draw2()Draw3() 保证表达式只会被计算一次, 如果不在编译时,则在运行时
  • 这三个变体的任何表达式是否将是 在编译时评估完全取决于编译器

编译器会为它们中的每一个生成不同的代码吗?如果是,哪一个会避免最冗余的计算?

【问题讨论】:

  • 我建议您观看此视频:youtube.com/watch?v=FnGCDLhaxKU。 Chandler 在那里明确指出了“const_cast”以及如何处理 const 的含义——也就是说,数据流之类的东西很难预测,所以最好简单地测试一下。
  • @atl 抱歉,我不明白 const_cast 与任何事情有什么关系。如果我有时间观看 2 小时的视频,我想也许我会理解这种联系......也许你可以总结一下?
  • 参见此处:goo.gl/GBcVKm
  • 附带说明,您甚至不必拥有那些静态(内部函数)。现在任何可以称为编译器的实体都会优化这些常量。
  • @CodyGray 不是真的...在优化编译器中发生了很多事情...而这两个小时只是皮毛而已。您甚至可以丢弃 Draw1 中的所有“常量”内容,它仍然会产生相同的结果。

标签: c++ optimization


【解决方案1】:

除非您尝试,否则无法确定您的编译器会做什么。编译所有三个代码示例,然后查看生成的目标代码。

实际上,它们应该都是相同的。在编译器优化方面,常量折叠是最容易实现的目标。如果您的编译器没有在编译时计算这些常量,则它不是一个优化编译器。除非您有一个非常充分的理由继续使用它,否则您应该将它交给垃圾堆并找到一个不同的。

【讨论】:

  • 我什至会使用一组更强大的词 - “如果您的编译器没有在编译时计算这些常量,请将其扔掉并使用另一个。”
  • @sergey 我最初是这样写的,但我认为您可能正在使用一个完全没有优化的特殊嵌入式编译器。不过,在这种情况下,您必须再次检查输出以了解发生了什么。
猜你喜欢
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
相关资源
最近更新 更多