C ++无法使用通用引用移动unique_ptr

时间:2014-07-22 10:17:30

标签: c++ c++11 move-semantics unique-ptr universal-reference

考虑以下代码:

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的拷贝构造函数,这当然是删除的。但为什么副本会在这里发生?我怎样才能编译这段代码?

2 个答案:

答案 0 :(得分:3)

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

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);
}

答案 1 :(得分:3)

我认为错误是在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);
}