【问题标题】:How to implement the move function in C++?如何在 C++ 中实现移动功能?
【发布时间】:2021-12-19 05:53:42
【问题描述】:

我想知道 C++ 中 move 函数的内部结构。 为此,我的目标是自己实现名为 move2 的移动函数。

这是我使用打印跟踪内存分配的实现。

#include <iostream>
#include <vector>

using namespace std;
void * operator new(size_t size) {
    cout << "New operator overloading " << endl;
    void * p = malloc(size);
    return p;
}

void operator delete(void * p) {
    cout << "Delete operator overloading " << endl;
    free(p);
}

template<typename T>
T move2(T& input) {
    cout << "Running move2 " << endl;
    return (T&&)input;
}

int main()
{
    {
        cout<<"Test#1"<<endl;
        vector<int> temp1(10,4);
        vector<int> temp2 = temp1;
    }
    {
        cout<<"Test#2"<<endl;
        vector<int> temp3(10,4);
        vector<int> temp4 = (vector<int>&&)(temp3);
    }
    {
        cout<<"Test#3"<<endl;
        vector<int> temp5(10,4);
        vector<int> temp6 = move(temp5);
    }
    {
        cout<<"Test#4"<<endl;
        vector<int> temp7(10,4);
        vector<int> temp8 = move2(temp7);
    }
    return 0;
}

这是输出

Test#1
New operator overloading
New operator overloading
Delete operator overloading
Delete operator overloading
Test#2
New operator overloading
Delete operator overloading
Test#3
New operator overloading
Delete operator overloading
Test#4
New operator overloading
Running move2
Delete operator overloading

我想知道我的 move2 实现是否正确,我可以在生产中使用它吗?

更新:

我找到了 move 的 GCC 实现

  /**
   *  @brief  Convert a value to an rvalue.
   *  @param  __t  A thing of arbitrary type.
   *  @return The parameter cast to an rvalue-reference to allow moving it.
  */
  template<typename _Tp>
    constexpr typename std::remove_reference<_Tp>::type&&
    move(_Tp&& __t) noexcept
    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

【问题讨论】:

  • 您的实现不正确。对比std::move的输入输出类型。
  • 为什么要重写std::move
  • @jarod42 在一次采访中我被要求重写std::move,后来我想出了move2。想知道正确的方法和实现以供将来参考。

标签: c++ move move-semantics


【解决方案1】:

std::move() 接受forwarding reference,并返回T&amp;&amp; 右值引用。你的move2() 也没有。它接受一个左值引用,并按值返回一个T

由于复制省略,您的代码“有效”,避免了当您的函数按值返回新对象时创建临时对象,从而允许使用您对 input 的类型转换引用直接构造 temp8,从而转移其数据的所有权。不过,这并不是因为正确的 move2() 实现。

试试这个:

template<typename T>
std::remove_reference_t<T>&& move2(T&& input) {
    ...
    return static_cast<std::remove_reference_t<T>&&>(input);
}

【讨论】:

  • 非常感谢。您的代码有效。但是,你能告诉我为什么 ``` template T&& move2(T&& input) { cout
  • @Heroman:参考折叠,如果T被推导出为U&amp;(如果你传递任何l值),你返回U&amp;而不是U&amp;&amp;
  • @Heroman 请参阅 cppreference.com 上的 reference collapsing
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
  • 2011-05-09
  • 2013-04-10
  • 2019-03-29
  • 2011-11-05
  • 2010-12-25
  • 1970-01-01
相关资源
最近更新 更多