ref是在复制编译器优化,我能避免它吗
Is ref-copying a compiler optimization, and can I avoid it?
我不喜欢指针,通常会尽量使用refs编写代码。
我已经为一个小型Win32应用程序编写了一个非常初级的"垂直布局"系统。大多数布局方法如下所示:
void Control::DoLayout(int availableWidth, int &consumedYAmt)
{
textYPosition = consumedYAmt;
consumedYAmt += measureText(font, availableWidth);
}
它们像这样循环通过:
int innerYValue = 0;
foreach(control in controls) {
control->DoLayout(availableWidth, innerYValue);
}
int heightOfControl = innerYValue;
它并没有在这里绘制内容,只是精确计算这个控件需要多少空间(通常还会添加填充等)。这对我来说非常有效……在调试模式下。
我发现,在Release模式下,我可以突然看到明显的、可记录的问题,当我在控件中循环并调用DoLayout()
时,consumedYAmt
变量在外部循环中实际上停留在0。最烦人的部分是,如果我插入断点并逐行遍历代码,这种情况就会停止,并且部分代码会由内部的"add"方法正确更新。
我在想这是否是一些编译器优化,他们认为我只是在int中添加ref标志,作为优化内存的一种方式;或者,如果有任何可能性的话,这实际上是以一种不同于看起来的方式工作的。
我会给出一个可重复性最低的例子,但我无法用一个小小的命令行应用程序做到这一点。我感觉到,如果这是一个优化,它只适用于较大的代码块和间接寻址。
编辑:再次抱歉信息普遍不足,但我现在得到提示,这可能是某种链接器问题。我在伪代码中跳过了继承模型的一部分:调用类实际上调用"Layout()
",这是该类根定义上的一个非虚拟函数。此函数执行一些与实现无关的逻辑,然后使用相同的参数调用DoLayout()
。然而,我现在注意到,如果我尝试向Layout()
添加断点,Visual Studio声称"断点不会被命中。调试器的目标代码类型的可执行代码都与此行关联。"我可以向某些其他行添加断点,但我开始注意到奇怪的步进逻辑,它拒绝进入某些函数,如Layout
。已尝试完全清除生成文件夹并重新生成。我将不得不继续寻找,因为我必须承认这并不是什么好事情
此外,随机添加:"控件"列表是一个包含shared_ptr对象的向量。我以前没有怀疑过循环机制,但现在我更仔细地观察了。
"consumedYAmt
变量实际上保持在0"
您描述的行为是特定优化的典型行为,这更多地是由于CPU而不是编译器。我怀疑您正在从另一个线程记录consumedYAmt
。对consumedYAmt
的更新根本无法到达其他线程。
这对CPU来说是合法的,因为C++编译器没有设置内存围栏。CPU编译器没有设置围栏,因为变量不是原子的。
在一个没有线程的小程序中,它根本不会显示出来,也不会在调试模式中显示出来。
由OP编写
好吧,最终解决了这个问题。尽管这个问题很简单,但由于发布模式的调试器似乎以不一致的方式运行,因此很难确定它。当我改变策略,在很多地方添加Logging语句时,我发现我的Control类有一个"mShowing"变量,它的构造函数中没有初始化。在调试模式下,它显然保留了未初始化的内存,我想这使它成为"true"——但在发布模式下,我最好的分析是内存保护使它默认为"false",事实证明,它在大多数时候都跳过了DoLayout方法的主体。
由于在整个过程中,响应者缺乏可处理的信息(如果我发布一个更长的例子,肯定会更容易),我只是简单地对每个提到未初始化变量的评论投了赞成票。
- 为什么要按值传递string_view?为什么Visual Studio不能优化这一点?
- 为什么编译器不能优化这个 std::string 构造?
- exp(-1/0.) == 0 是否确定即使使用 -ffast-math 优化也能成立?
- 是否有针对递归功能的部分尾声优化
- 避免从函数返回时进行复制,而不依赖编译器优化
- 为什么 GCC 不能优化出 'std::sqrt'?
- 如何避免编译器优化某些操作
- 避免使用多线程c++优化的变量
- 当不能使用auto和decltype()时,如何避免封闭类类型的重复
- 如何避免 C++ 编译器优化器删除静态变量代码
- ref是在复制编译器优化,我能避免它吗
- 为什么编译器不能优化std::string concat
- gcc会自动使用-j4吗?我能做些什么来优化我的编译吗
- 我怎么能用这个OpenMP关键部分来避免这个原始指针呢
- 返回值优化:我可以避免复制构造巨大的STL容器吗
- 当我在类中声明一个固定长度的向量时,我能避免歧义吗?
- c++:避免优化变量
- 我能避免在我的设计中传播这个模板吗?
- 如何判断代码是否不能进一步优化
- 带有继承的部分专门化.我能避免继承吗?