在setter中验证值是否不同有意义吗?

Does it make sense to verify if values are different in a setter

本文关键字:有意义 是否 setter 验证      更新时间:2023-10-16

我记得我在某个地方(可能在Github)看到过这样一个setter中的例子:

void MyClass::setValue(int newValue)
{
    if (value != newValue) {
        value = newValue;
    }
}

对我来说,这没有多大意义,但我想知道它是否能提高性能。

对于scalar types没有意义,但对于某些user-defined类型可能有意义(因为type可能非常"大",或者它的赋值运算符可以做一些"困难"的工作)。

指令管道越深(至少在Intel平台上它只会变得越来越深),分支错误预测的代价就越高。

当分支错误预测时,来自错误预测的一些指令路径仍然通过管道移动。所有的工作都在这些上面进行指令被浪费了,因为它们不会被执行分支被正确预测

所以,在代码中添加if实际上会损害性能。写操作将被L1缓存,可能会缓存很长时间。如果写操作必须是可见的,那么操作就必须是联锁的。

您可以真正判断的唯一方法是通过实际测试不同的替代方案(基准测试和/或分析代码)。不同的编译器,不同的处理器和不同的代码调用它会有很大的不同。

一般来说,对于"简单"的数据类型(int, double, char,指针等),它是没有意义的。它只会使代码对处理器来说更长更复杂[至少如果编译器按照你的要求去做-它可能会意识到"这没有任何意义,让我们删除这个检查-我不会依赖它' -编译器通常比你聪明,但让编译器的生活变得更加困难几乎不会带来更好的代码]。

编辑:另外,只有比较容易比较的东西才有意义。如果在相等的情况下难以比较数据(例如,如果长字符串相等,则需要从两个字符串中读取大量数据[或字符串开头相同,仅在最后几个字符中有所不同])。所以储蓄很少。这同样适用于具有一堆成员的类,这些成员通常几乎都是相同的,但有一两个字段不是,依此类推。另一方面,如果您有一个"客户数据"类,它有一个必须是唯一的整数客户ID,那么只比较客户ID将是"便宜的",但是复制客户姓名、地址、电话号码和客户的其他数据将是昂贵的。[当然,在这种情况下,为什么它不是(智能)指针或引用?]。编辑结束。

如果数据在不同的处理器之间被"共享"(多个线程访问相同的数据),那么它可能会有一点帮助[特别是如果这个值经常被读取,并且经常以与以前相同的值写入]。这是因为从其他处理器的缓存中"踢出"旧值是昂贵的,并且只有在实际更改某些内容时才希望这样做。

当然,只有当你知道自己的代码处于性能热点的前沿时,才有必要担心性能问题。在其他任何地方,使代码尽可能容易读、清晰和简洁总是最好的选择——这通常也会使编译器更能够确定实际发生了什么,并确保最佳的优化结果。

这种模式在Qt中很常见,其中API高度基于信号&槽。此模式有助于在循环连接的情况下避免无限循环。

在不存在信号的情况下,这段代码只会降低性能,正如@remus-rusanu和@mats-petersson所指出的那样。