将 std::forward_as_tuple() 结果传递给可能从该对象的 rvalue-reference 成员移动的多个函数?
Passing std::forward_as_tuple() result to multiple functions that may move from that object's rvalue-reference members?
编辑:我想我所问的最有可能的用例是创建一个从std::forward_as_tuple()
接收右值引用元组的函数
之所以想到这个问题,是因为我正在检查传递给构造函数初始化器的对象的成员,看看它们是否是右值引用(我愿意接受建议,告诉我这是错误的,错误的……希望遵循经验法则,在未来避免这种情况,但这就是问题的原因)。我突然想到,在一个稍微不同的上下文中,我可能会将一个具有右值引用成员的对象交给多个函数(或函数对象),我可能控制也可能不控制,这些函数可能会从这些成员中移动。
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));
}
我看过右值参考成员的使用?,以及其他一些关于右值参考成员的讨论,但我不能完全解决这个问题。
我不仅仅是问会发生什么,而是问这种情况是否应该/可能发生,以及在传递包含右值引用成员的对象时要记住什么关键规则。
在此代码中,func_i_dont_control
无法静默地窃取参数。只有右值绑定到右值引用,并且命名变量不是右值。您的代码要么编译失败,要么func_i_dont_control
(有一个重载)不使用移动语义。
为了让func_i_dont_control
有机会窃取元组(将元组绑定到右值引用),必须使用std::move(tup)
将其显式强制转换为右值。
(采用左值引用的函数不应该从中移动,否则我们真的无法判断会发生什么。)
编辑但问题似乎不是元组本身,而是它的成员。同样,这些成员不会是右值,所以func_i_dont_control
需要显式地移动它们。我认为它没有这样做的"道德权利"*,除非它将整个元组作为右值接收,而这在你的函数中没有发生。
*对于移动语义,您必须遵循某些准则。基本上,你可以将任何东西强制转换为右值并从中移动,不管你是在处理左值还是右值引用。只要遵循这些准则,移动语义就会正常工作。如果您开始不顾这些准则将事物强制转换为右值,则对象将在函数调用等之后开始消失。
元组和可变模板的使用似乎偏离了问题的重点,所以让我重新表述一下:
void func(std::unique_ptr<Foo>&& foo) {
std::unique_ptr<Foo> bar1(std::move(foo));
std::unique_ptr<Foo> bar2(std::move(foo));
}
这里发生了什么?好吧,bar2
总是包含一个空指针(而bar1
可能会,这取决于foo
的原始值)。
不存在未定义的行为,因为移动构造函数应该使对象处于可用状态需要引用,正是出于安全原因。因此,您可以使用从移动到的对象,但是它的状态可能不是很有趣:它甚至不需要等效于默认的构造状态,它可能只是一个过时的状态。
- 对RValue对象调用的LValue ref限定成员函数
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- 如果没有带有函数签名的 rvalue 参数,是否会执行 C++ 11 中的移动语义?
- 警告:返回对临时 - 奇怪情况的引用(对 Rvalue 的澄清)
- C++标准是否保证失败的插入到关联容器中不会修改 rvalue-reference 参数?
- 未执行lvalue到rvalue转换
- 什么是可修改的rvalue
- 为什么捕获std :: Isringstream的RVALUE的OP会失败
- 是任务的正确操作数总是转换为rvalue
- RVALUE参考与const lVALUE参考作为参数之间的混淆
- 如何使对象通过RVALUE参考通过而没有复制
- 与构造函数中rvalue结合的非const lvalue有关的错误
- RVALUE参考与LVALUE结合
- RVALUE参考和多态性
- 是转发参考是否仍然是RVALUE参考
- 如何声明功能接受rvalue的任意长度阵列
- 在平等符号左侧使用RVALUE参考的规则是什么?
- 为什么不将RVALUE引用定义为RVALUE表达
- 如何将rvalue作为参考参数传递给函数
- 返回rvalue的共享_ptr成员