C++习语:如何将rvalue作为rvalue传递?

3
以下代码无法编译。Clang 显示以下错误信息: candidate function not viable: no known conversion from 'A' to 'A &&' for 1st argument 这似乎是因为f()内的a被视为左值。
struct A{};

void g(A&& a){
    return;
}

void f(A&& a){
    g(a);
}

int main(){
    return 0;
}

这是合理的,因为防止f()调用g()多次。
以下方案可以修复我的代码:
g(std::move(a)); 

但在我看来似乎有问题:如果有人修改f()的签名为void f(A& a)会发生什么。

是否有更好的惯用语?


也许您可以使用完美转发,即 template<typename T> void f(T&& a) { g(std::forward<T>(a)); ,再加上某种 SFINEA 以阻止除 A 类型之外的类型。... 不过我觉得原始代码没有任何问题。 - M.M
1个回答

5

但是我认为这看起来不对:想象一下如果有人修改f()的签名为void f(A& a)会发生什么。

根据参数值类别更改函数签名是一种破坏性的变化,可能需要手动检查该函数的每个调用。您不会找到一个C++习语,可以神奇地适应这种变化。

"修复"g(std::move(a))是保留函数参数rvalue的正确方式。如果g应该操作一个rvalue,请坚持使用它。如果您后来决定g不接受rvalue,则没有意义,但您仍想传递一个lvalue,请对其进行重构-并调整调用。在这种特殊情况下,编译器将帮助您拒绝将rvalue绑定到函数参数A&a


那么,如果我理解正确的话,“Constructor(unique_ptr<A>&& uniquePtr) : mySharedPtr_(std::move(uniquePtr)) {}”是用输入的uniquePtr初始化shared ptr数据成员的正确方式。我是对的吗?谢谢。 - jimifiki
是的,没错。std::shared_ptr可以使用右值std::unique_ptr参数进行构造。 - lubgr
1
@jimifiki 如果你在 uniquePtr 中使用值传递而不是右值引用,那么情况会稍微好一些。这样调用者就可以确信 std::move 确实移动了参数。 - local-ninja

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接