我在公司中看到了很多代码,其中函数带有右值参数。
示例:
void Notifier::PostEvent(std::unique_ptr<IEvent>&& event)
{
std::unique_lock<std::mutex> lock(m_Mutex);
m_events.push_back(std::move(event));
m_conditionVariable.notify_all();
}
这里没有模板。这很容易这样写:
void Notifier::PostEvent(std::unique_ptr<IEvent> event)
{
std::unique_lock<std::mutex> lock(m_Mutex);
m_events.push_back(std::move(event));
m_conditionVariable.notify_all();
}
由于在两种情况下,参数“事件”均为接收器值,因此它们实际上是相同的。我认为第一个版本的唯一优点是,它为unique_ptr保存了一个move构造函数。那是对的吗?真的值得吗?
答案 0 :(得分:3)
好的。现在,我在阅读How do I pass a unique_ptr argument to a constructor or a function?
之后会更好地理解发生的事情是,在我的第一个示例中,我通过右值引用传递,它或多或少类似于通过非常量左值引用传递。尽管您可能希望函数调用后参数为空,但不能保证。这完全取决于该功能实际使用的功能。通过将其推入/移动到像我在这里一样的向量中,unique_ptr将为空。但是,如果我不做任何移动(例如,我只是调用IEvent类的方法),则unique_ptr不会为空。
因此,unique_ptr右值引用参数实际上并不能保证调用后该值发生什么变化,即它是否为接收器。通话后可能为空,也可能不是。只有检查代码,您才能确定会发生什么。
回想一下,第二个函数定义按值需要一个unique_ptr更好。这样可以确保unique_ptr已被移动,以后不再使用。