无法用通用引用移动unique_ptr

C++ Unable to move unique_ptr with universal references

本文关键字:unique 移动 ptr 引用      更新时间:2023-10-16

考虑以下代码:

template<typename T>
T mov(T&& t){
   return std::move(t);
}
int main(){
   std::unique_ptr<int> a = std::unique_ptr<int>(new int());
   std::unique_ptr<int> b = mov(a);
}

mov函数应该简单地接受一个通用引用并按值返回它,但通过move而不是复制它。因此,在调用此方法时不应涉及复制。因此,使用只能移动的unique_ptr来调用这样的函数应该是好的。但是,这段代码不能编译:我收到错误:

test.cpp:24:34: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
    std::unique_ptr<int> b = mov(a);

因此,c++似乎试图调用unique_ptr的复制构造函数,当然它被删除了。但为什么这里会发生复制呢?我怎样才能得到这个代码编译?

我认为错误是在mov的返回类型

代码应该是

#include <utility>
#include <memory>
template<typename T>
typename std::remove_reference<T>::type&& mov(T&& t){
   return std::move(t);
}
int main(){
   std::unique_ptr<int> a = std::unique_ptr<int>(new int());
   auto b = mov(a);
}

这个问题暗示了一个按值返回的场景,这也可以编译。我不确定它是否适用于你的情况;

template<typename T>
typename std::remove_reference<T>::type mov(T&& t){
   return std::move(t);
}

我终于找到了一个可行的解决方案。我认为问题是按值返回,这将触发一个副本。相反,我需要通过右值引用返回;然后将自动进行移动。首先我试了这个:

template<typename T>
T&& mov(T&& t){
   return std::move(t);
}
但是现在,问题是返回类型T&&通用引用,而不是右值引用。因此,当调用带有左值的函数时,实际签名是T& mov(T& t)。因此,它的主体将无法编译,因为我不能将std::move转换为左值引用。这就是发生的事情,下面是错误:
test.cpp:18:22: error: invalid initialization of non-const reference of type 
‘std::unique_ptr<int>&’ from an rvalue of type ‘std::remove_reference<std::unique_ptr<int>&>::type {aka std::unique_ptr<int>}’
    return std::move(t);

所以,我需要一个实右值引用作为返回类型。起初,我不知道如何构造它,但最后,我发现我首先需要std::remove_reference类型T,然后添加&&,然后我将有一个实右值引用T&&。这个版本的mov编译得很好,解决了这个问题:

template<typename T>
typename std::remove_reference<T>::type&& mov(T&& t){
   return std::move(t);
}

正如Niall所说,通过引用返回也可以通过使用remove_reference而不使用&&来工作:

template<typename T>
typename std::remove_reference<T>::type mov(T&& t){
   return std::move(t);
}