为什么自定义移动函数不能像 std::move 那样工作

问题描述 投票:0回答:1

只是为了看看 std::move 是如何工作的,我尝试模仿(很好地复制了原始代码)std::move 函数;但令我惊讶的是它不能像 std::move 那样工作。我的 move 函数最终调用了 copy ctor 而不是 move ctor。

#include <iostream>

#define My_version

template <class _Ty>
struct remove_reference {
    using type = _Ty;
    using _Const_thru_ref_type = const _Ty;
};
template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;

#ifdef My_version
template<typename T> // in namespace std
typename remove_reference<T>::type&&
mymove(T&& param)
{
    std::cout << "My_version\n";
    using ReturnType = typename remove_reference<T>::type&&; 
    return static_cast<ReturnType>(param);
}
#else
template <class _Ty>
constexpr remove_reference_t<_Ty>&& mymove(_Ty&& _Arg) noexcept { // forward _Arg as movable
    return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}
#endif // My_version

class simple
{
public:
    simple(int kk) :k(kk) {}
    
    simple(simple&& rhs) noexcept
    {
        std::cout << "move is called \n";
        k = rhs.k;
        rhs.k = -1; //moved
    }

    simple(const simple& rhs)noexcept
    {
        std::cout << "copy is called \n";
        k = rhs.k*10;
    }
    int k;
};

int main()
{
   
        {
            std::cout << "===============================\nmymove\n===============================\n";
            simple a(42);
            simple b = mymove(a);
            std::cout << " after move\nmovedObj.k " << b.k << " originalObj.k " << a.k << "\n";
        }
        {
            std::cout << "\n\n===============================\nstd::move\n===============================\n";
            simple a(42);
            simple b = std::move(a);
            std::cout << "after move\nmovedObj.k " << b.k << " originalObj.k " << a.k << "\n";
        }
   return 0;
}

我尝试了 std::move 函数的精确副本和略有不同的样式函数,如这里所示,由 #ifdef 分隔。与 std::move 不同,两者都调用复制构造函数。

std::move 会导致移动构造函数,为什么我的 move 函数会导致复制。

===============================
mymove
===============================
copy is called
 after move
movedObj.k 420 originalObj.k 42


===============================
std::move
===============================
move is called
after move
movedObj.k 42 originalObj.k -1
c++ c++17 move stdmove
1个回答
0
投票

按照HolyBlackCat的建议,为remove_reference添加另外两个参考专业化解决了问题。

模板结构remove_reference<_Ty&> { 使用类型 = _Ty;使用 _Const_thru_ref_type = const _Ty&; };

模板结构remove_reference<_Ty&&> { 使用类型 = _Ty;使用 _Const_thru_ref_type = const _Ty&&; };

© www.soinside.com 2019 - 2024. All rights reserved.