在 set 方法中赋值前检查当前值

Check current value before assignment in set method

我将从我在 Internet 上找到的应用程序的代码片段开始。它是用 C++ 制作的,但该主题可以针对任何编程语言:

class AppSettings
{

public:
    AppSettings() {m_value = 0;}
    ~AppSettings();

    void AppSettings::setValue(uint value)
    {
        if (m_value != value)           
            m_value = value;
    }

private:
    uint m_value;
};

您真的需要在赋值前检查当前值与新值是否不同吗? 仅仅是编程风格、效率、礼貌还是什么?

一般来说,在class的set方法中,是否需要检查新值是否与当前值不同?

Do you really need to check that the current value differs from the new one before assignment? Is it just a programming style, efficiency, good manner, or what?

我觉得像 cruft

当您在编写代码时混合两种想法("We only update state when necessary" 与 "the setter just sets the value")时,您通常会得到这样的代码,并且示例代码最终没有清楚地表达任何一种想法。

虽然我不能说 - 我必须阅读你从中获取代码的文章。

General speaking, in set method of a class, do you need to check that new value differs from current one?

你做,当你优化,或者当你需要用代码表达的想法是"perform updates when necessary"。

考虑这个(人为的和设计的)代码:

/// object in 2D space
class TwoDObject
{
    /// shift object position
    void shift_position(int x, int y)
    {
        if(x != x_ || y != y_)
        {
            x_ = x;
            y_ = y;
            render_shadows();
        }
    }

private:

    // render the shadows cast by this object (slow implementation)
    void render_shadows();

    int x_;
    int y_;
};

在这种情况下,你有一个内部状态更新,然后是副作用(当你改变位置时阴影已经改变)。

因为渲染阴影的方法很慢,所以只在需要的时候调用它。

这在很大程度上取决于被分配成员的类型。如果它是原始类型或同样轻量级的东西,则检查很可能是悲观的:分配可能比条件跳转便宜得多。请记住,基本上所有现代处理器都是基于流水线的,如果分支预测失败,条件跳转会导致需要中止流水线。这会降低效率。

如果类型的分配成本更高,答案就不那么明确了。例如,复制大量数据缓冲区是一项代价高昂的操作。但是,比较它的相等性也是如此。要决定是盲目分配还是先比较,您需要了解所讨论类型的特性,并评估相同的频率-可能会发生值分配,识别它们的速度有多快,以及与复制相比这种识别的成本有多高 "blindly." 另外请记住,如果比较表明它们的值不同,那么您将为两者付出代价:比较,然后复制。

最后,有些情况需要检查:当赋值有副作用时。例如,如果成员的类型使其在分配给时发出通知,您很可能需要进行比较以避免虚假通知(当然,假设您不想要这些通知)。

总而言之,没有硬性规定,但我想说的是,平均而言,只有在有充分理由的情况下才应该包括比较。

这实际上取决于您要设置的内容,我的意思是,如果您设置的内容会传播更改,那么执行此操作很重要。如果在这种情况下更改的成本相当大(重新排序整个数组、更新某个网络位置的数据、重写一个大文件),并且如果程序需要实时性能,那么检查不必要的更改是一个很好的做法。如果更改没有副作用,最好只是更改它并避免额外的分支。