当一个函数接受一个它在一些分支中没有使用的右值引用时,它应该如何处理rvalue以保持其签名的语义正确性并且对于所有者的所有权保持一致数据。考虑以下示例代码:
#include <memory>
#include <list>
#include <iostream>
struct Packet {};
std::list<std::unique_ptr<Packet>> queue;
void EnQueue(bool condition, std::unique_ptr<Packet> &&pkt) {
if (condition) queue.push_back(std::move(pkt));
else /* How to consume the pkt? */;
}
int main()
{
std::unique_ptr<Packet> upkt1(new Packet());
std::unique_ptr<Packet> upkt2(new Packet());
EnQueue(true, std::move(upkt1));
EnQueue(false, std::move(upkt2));
std::cout << "raw ptr1: " << upkt1.get() << std::endl;
std::cout << "raw ptr2: " << upkt2.get() << std::endl;
return 0;
}
Enqueue函数的签名表示它将获取传递给它的数据的所有权,但只有当它到达 if 路径时才会成立,而是如果它到达 else < / strong>路径函数有效地不使用rvalue并且所有权返回给调用者,这可以通过upkt2.get从函数返回后不 NULL来说明。实际效果是EnQueue的行为与其签名不一致。
现在的问题是 - 这是否是可接受的行为,或者EnQueue函数是否应该更改为一致,如果是这样的话?
答案 0 :(得分:0)
我看到了三种解决方法。
记录函数退出后,“pkt
处于有效但未指定的状态。”这样,调用者之后就不能对该参数做任何假设;如果他们需要它无论如何都被清除,他们可以明确地做到。如果他们不这样做,他们就不会支付他们不会使用的任何内部清理费用。
如果您希望在接受所有权时100%明确签名,只需按值pkt
而不是右值参考(在评论中由@Quentin建议)。
从pkt
:
if (condition) queue.push_back(std::move(pkt));
else auto sink(std::move(pkt));