7

问题

我们可以使用移动语义来移动堆栈上的堆分配对象吗?

例子

#include <boost/asio.hpp>
#include <memory>

class connection
{
public:
    connection(boost::asio::ip::tcp::socket&& socket);

    void start();

private:
    boost::asio::ip::tcp::socket m_socket;
};

class server
{
public:
    // Not relevent here

private:
    void accept();

    boost::asio::io_service        m_io_service;
    boost::asio::ip::tcp::acceptor m_acceptor;
};

void server::accept()
{
    auto socket = new boost::asio::ip::tcp::socket(m_io_service);

    m_acceptor.async_accept(*m_socket,
    [&, socket](const boost::system::error_code& error)
    {
        if (!error)
        {
            auto connection = std::make_shared<connection>(std::move(*socket));
            connection->start();
        }

        accept();
    });
}
4

1 回答 1

8

std::move不重定位对象。它移动值。(想想MOV R1, R2某种机器语言中的一条指令:它不移动寄存器,只移动内容!或者memmove库函数。这是“移动”的感觉,而不是复制或压缩垃圾收集器时发生的那种移动,这会导致对象驻留在不同的地址,同时保留其确切身份,这涉及在机器中的任何地方找到对移动对象的每个引用并更新它)。

移动语义是 C++ 中的一项新功能,它允许以不必保留旧值的方式复制对象。这在不再需要旧对象的情况下很有用,因为它可以更快。

例如,将一个向量从一个向量移动std::vector<X>到另一个向量会导致源对象是一个长度为零的向量,并且所有数据都可以在没有任何内存分配或复制的情况下移动。由于想法是不使用旧向量,因此它已被破坏为零长度并不重要。

鉴于此类操作数之间的复制构造在 C++ 中一直运行良好,因此没有理由在不同存储(例如,自由存储(“堆”)到自动存储(“堆栈”)中的位置之间不起作用。

[编辑 2020]

但是,如果我们将一个对象从堆中移动到其他地方,就会出现问题。堆中的旧内存只是被丢弃,没有任何破坏。那个记忆不再是一个对象;要再次使用它,我们必须在其中移动或构造一个对象。否则,我们应该删除它(以低级方式,不调用析构函数)。

于 2012-04-20T02:33:42.817 回答