为什么自动返回类型在此示例中丢失了移动语义?

时间:2018-02-12 12:42:54

标签: c++ templates auto c++17

我正在观看video尼古拉说自动失去移动语义的例子:

@Override
public boolean equals(final Object other) {
    if (!(other instanceof Box)) {
        return false;
    }
    return new EqualsBuilder().appendSuper(super.equals(other)).isEquals();
}


/**
 * {@inheritDoc}
 */
@Override
public int hashCode() {
    if (this.hashCode == 0) {
        this.hashCode = new HashCodeBuilder().appendSuper(super.hashCode()).toHashCode();
    }
    return this.hashCode;
}

我在想:

  1. 为什么会这样?

  2. guaranteed RVO启动了吗?         这个例子?如果是这样,有什么值得担心的?

1 个答案:

答案 0 :(得分:8)

我认为尼古拉本来可以说得更好一点。

当您按auto返回时,您的函数会返回(其类型将被推断)。如果std::invoke返回纯净的右值或x值,那么call的结果当然会相应地构建(如果可能的话,通过移动)。在这个意义上,我们不会“失去动作语义”。

但是当我们按值返回时,需要创建该值对象。它可以通过移动创建,在某些情况下(which aren't present here)可以省略它,但必须创建它。保证副本省略不允许我们删除创建此对象。

如果std::invoke给我们一个xvalue(对某事的右值引用),那可能会非常浪费。我们为什么要构造一个返回它的对象?

这就是为什么一两张幻灯片后他说我们应该按decltype(auto)返回。然后,扣除规则将保留对std::invoke

的调用的值cateogry
  1. 如果它返回一个值,我们就不会更糟。我们自己的call将返回一个值(可以通过移动std::invoke的返回值来创建它。)

  2. 如果std::invoke返回左值(X&)或xvalue(X&&),则会按原样返回,而不会通过复制或移动创建其他对象。