c – 将std :: forward_as_tuple()结果传递给可能从该对象的rvalue-reference成员移动的多个函数?

编辑:我认为我所询问的最可能的用例是创建一个从std :: forward_as_tuple()接收rvalue-references元组的函数.

想到这个问题的原因是因为我正在检查传递给构造函数初始值设定项的对象的成员,看看它们是否是rvalue-references(我很乐意告诉我这是错误的错误…希望随后是未来要避免这种情况的经验法则,但这就是提出这个问题的原因).在我看来,在一个稍微不同的上下文中,我可能最终将具有rvalue-reference成员的对象交给多个函数(或函数对象),我可能控制也可能不控制,这可能会从这些成员移动.

template<typename... Args>
void my_func(std::tuple<Args...>&& tup) {

    //if tup's members are rvalue references,
    //and this function moves guts from tup members, then...
    func_i_dont_control(tup); 

    //what happens here if moves are done on the same members?
    another_func_i_dont_control(std::move(tup));
}

我已经查看了Use of rvalue reference members?,以及其他一些关于右值参考成员的讨论,但是我无法明确地将其排除在外.

我不只是询问会发生什么,而是这个场景是否应该/甚至可能发生,以及在传递包含rvalue-reference成员的对象时要记住哪些关键规则.

最佳答案 在此代码中,func_i_dont_control无法以静默方式窃取参数.只有rvalues绑定到rvalue引用,而命名变量不是rvalue.您的代码无法编译,或者func_i_dont_control(具有重载)不使用移动语义.

为了给func_i_dont_control提供窃取元组的机会(将元组绑定到rvalue引用),必须使用std :: move(tup)将其显式地转换为rvalue.

(一个带左值参考的函数不应该从它移动,否则我们真的不知道会发生什么.)

编辑但问题似乎不是关于元组本身,而是其成员.同样,这些成员不会是rvalues,因此func_i_dont_control需要显式移动它们.我不认为它有这样做的“道德权利”*,除非它将整个元组作为一个rvalue接收,这在你的函数中没有发生.

*使用移动语义,您必须遵循某些准则.基本上你可以向rvalue投射任何东西并从中移动,如果你正在处理左值或右值引用并不重要.只要遵循这些准则,移动语义就能正常工作.如果你开始向rvalues投射东西而不考虑那些指南,那么在函数调用之后对象将开始消失.

点赞