当变量不是本地变量时,我应该继续 return 吗?

Should I move on return when variables are not local

有几个关于复制省略和移动的问题。 假设我有以下代码:

class A {};

class B {
public:
    A get1() const {
        A local_var;
        return local_var;
    }
    A get1bad() const {
        A local_var;
        return std::move(local_var);
    }
    A get2() const {
        return member_var;
    }
    A get3() const {
        return std::move(member_var);
    }
private:
    A member_var;
};

我看到很多人说不要继续前进 return。 据我所知,这是因为使用复制省略,在 case get1 上,编译器不会调用构造函数 + 移动构造函数,而只会调用默认构造函数,而 case get1bad 强制编译器调用构造函数 + move。

我的问题是关于变量不是本地变量的情况(get2 与 get3)。 在这种情况下,无论如何都会在 class 中构造变量。在 get2 中,我看不到任何可能的优化。在这种情况下,如果我真的不关心确保 class B 有一个有效的 A 对象,那么实际移动不是更好吗?不就是调用移动构造函数吗,一般比复制构造函数便宜?

A get3() const {
    return std::move(member_var);
}

你有一个const函数,所以该成员也被认为是const,无论如何都不会移动。

你可以考虑A get3() &&在你有临时B时移动成员。也许吧,如果这种情况经常发生的话。

getter 总是 会破坏 class' 值,即使它是左值,这似乎是一个罕见的用例。

I read a lot of people saying to not do move on return. From what I gather it's because with copy elision, on case get1, the compiler will not call constructor + move constructor but rather just one call to the default constructor, while case get1bad forces the compiler to call constructor + move.

如果 return 语句的操作数只是局部变量的名称,那么 std::move 基本上是隐式应用的。所以充其量 return std::move(local_var); 是多余的。这是 return 的特殊规则。它不适用于其他地方。

然而,使用 return std::move(local_var); 使得强制复制省略规则不再适用,这就是为什么它不仅是多余的,而且比 return local_var;.[=29 更糟糕的原因=]


My question is regarding cases where the variable is not local (get2 vs get3). In that case, the variable is constructed anyway in the class. In get2 there's not really any optimization that I can see being possible. In this case, if I don't really care about ensuring class B has a valid A object, wouldn't it be better to actually move? Wouldn't it just call the move constructor which is generally cheaper than the copy constructor?

在您的示例中,所有成员函数都是 const 合格的。因此 std::move(member_var) 的类型将是 const A&&。移动构造函数采用 A&&,而不是 const A&&。因此不会发生任何移动,并且复制构造函数将用于 get2get3 的 return 值。

如果删除 const 限定符,那么 yes return std::move(member_var); 在这种情况下是有意义的,并且允许移动构造而不是复制构造。 Copy/move 在这两种情况下都不可能省略,因为变量不是函数的局部变量。


您不太可能在调用成员函数后不关心 member_var 的状态,因此这在实践中不太可能有意义。如果我会用 && 限定成员函数,那么它仅在 class 实例是右值时才使用,这是我能想到的唯一不关心的情况调用成员函数后的对象状态。