【问题标题】:How does one force a C++ move operator without std:whatever [closed]如何在没有 std:whatever 的情况下强制使用 C++ 移动运算符 [关闭]
【发布时间】:2018-12-04 02:13:10
【问题描述】:

我有一个非常大的代码库,已经存在了一段时间。我一直在通过选择性地使用新的语言功能来更新它。我打算使用移动构造函数,但我什至无法想出一个复杂的场景来实现它。我不会将我什至无法进行单元测试的代码放入我的代码库中。

而且,我不能使用 std:move,因为我根本不使用标准库。我有自己的标准库,以及我自己的所有其他内容(大约一百万行代码)。所有内容都隐藏在一个不会向外界公开任何语言或平台头文件的虚拟内核中。

所以我不能使用 std::move。希望它不会做任何我做不到的神奇事情?而且我猜想在面对基类时也需要类似的东西来处理移动构造函数(几乎总是如此。)如果它确实做了一些神奇的事情,那就是库泄漏到语言中并且不会很好。

显然 Visual C++(在我的例子中是 2017 年)上没有编译设置来禁用它从省略构造函数中,这大概是为什么我无法做任何事情甚至导致它。

当然,这也引发了一个问题,即如果需要这么多努力(即使在非优化模式下)来实现它,它是否无用。

【问题讨论】:

  • 我不知道,您是否尝试过查看std::move 的源代码?
  • 如果你有自己的标准库,自然会拥有自己的std::move。合乎逻辑。
  • 你 static_cast 到一个右值引用。
  • "如果它确实做了一些神奇的事情,那就是库泄漏到语言中并且不会很好。" 虽然std::move 几乎不是“神奇”,但我会强烈建议您不要将 C++ 标准库视为与 C++ 语言不同的构造。仍然需要 C++ 的独立实现来提供基本功能。这样的实现可能不提供容器、iostream 或其他任何东西,但是库的很多部分您要么无法自己实现,要么与语言特性有些相关。
  • 我将静态转换为 r 值。编译器仍然只是删除了整个内容并直接构建到目标中,甚至没有调用复制 ctor。

标签: c++ move-constructor


【解决方案1】:

我不能使用 std:move,因为我根本不使用标准库...希望它不会做任何我做不到的神奇事情?

来自How does std::move() transfer values into RValues?

template <typename T>
typename remove_reference<T>::type&& move(T&& arg)
{
    return static_cast<typename remove_reference<T>::type&&>(arg);
}

This answer 详细解释了它的工作原理。

我打算玩弄移动构造函数,但我什至想不出一个复杂的场景来实现它。

调用移动构造函数并不难。例如:

template< class T > struct my_remove_reference      {typedef T type;};
template< class T > struct my_remove_reference<T&>  {typedef T type;};
template< class T > struct my_remove_reference<T&&> {typedef T type;};

template <typename T>
typename my_remove_reference<T>::type&& my_move(T&& arg)
{
    return static_cast<typename my_remove_reference<T>::type&&>(arg);
}

struct S
{
    int *ptr = nullptr;

    S() = default;
    S(int *p) : ptr(p) {}
};

class MoveTester
{
private:
    int *m_ptr = nullptr;

public:
    MoveTester() = default;
    MoveTester(const MoveTester &) = delete;
    MoveTester(MoveTester&& src) : m_ptr(src.m_ptr) { src.m_ptr = nullptr; }

    MoveTester(int *ptr) : m_ptr(ptr) {}
    MoveTester(S&& src) : m_ptr(src.ptr) { src.ptr = nullptr; }

    MoveTester& operator=(const MoveTester &) = delete;
    MoveTester& operator=(MoveTester&& rhs) { m_ptr = rhs.m_ptr; rhs.m_ptr = nullptr; return *this; }
    MoveTester& operator=(int *rhs) { m_ptr = rhs; return *this; }
    MoveTester& operator=(S&& src) { m_ptr = src.ptr; src.ptr = nullptr; return *this; }

    void display(const char *name) const { cout << name << ".m_ptr = " << m_ptr << endl; }
};

int* int_to_ptr(intptr_t value) { return reinterpret_cast<int*>(value); }

int main()
{
    MoveTester mt1;
    mt1.display("mt1");

    MoveTester mt2 = int_to_ptr(12345);
    mt2.display("mt2");

    //MoveTester mt3 = mt2; // compiler error! Copy constructor is deleted
    MoveTester mt3 = my_move(mt2);
    mt2.display("mt2");
    mt3.display("mt3");

    MoveTester mt4 = S();
    mt4.display("mt4");

    MoveTester mt5 = S(int_to_ptr(67890));
    mt5.display("mt5");

    //mt1 = mt5; // compiler error! Copy assignment is deleted
    mt1 = my_move(mt5);
    mt1.display("mt1");
    mt5.display("mt5");

    mt1 = int_to_ptr(13579);
    mt1.display("mt1");

    mt1 = S();
    mt1.display("mt1");

    mt1 = S(int_to_ptr(24680));
    mt1.display("mt1");

    return 0;
}

Live Demo

【讨论】:

  • 我很好奇 - 你不认为这个问题是重复的吗?
  • 也许正在寻找难以捉摸的Reversal 徽章;)
  • 谢谢,我会试试的。我正在对 R 值进行强制转换,但错过了删除参考位。虽然,我对一件事有点不清楚......我假设在调用代码中使用 my_move 纯粹是为了强制它发生?如果外部世界必须强制移动ctor,那是没有用的。我认为 my_move 除了用于强制测试之外,仅用于处理 move ctor 中的基类,对吗?否则编译器本身会看到移动 ctor 的机会和可用性并执行所需的操作?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
  • 1970-01-01
  • 2013-10-30
  • 1970-01-01
相关资源
最近更新 更多