仅使用移动构造函数在 std::map 中插入类

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

我有一个类,既不实现默认构造函数,也不实现复制构造函数,只实现移动构造函数,并且在函数内部我想将此类的新实例插入 std::map 中,但是当我使用

std::move
为此,我的实例仍然在函数作用域结束时被销毁,不是应该将实例的所有权移至容器吗?


class Server {
  public:

    friend class Client;
    class Client {
      public:
        Client() = delete;
        Client(const Client &) = delete;
        Client(Client &&) = default;
        ~Client() {
          ::close(m_fd);
        }
        Client & operator =(const Client &) = delete;
        Client & operator =(Client &&) = default;
    
      private:
        Client(int fd, const in_addr & addr) : m_fd(fd), m_addr(addr) {}
      
        int m_fd;
        in_addr addr;
    };

  private:
    void m_acceptClient() {
      sockaddr_in addr;
      socklen_t addrLen = sizeof(addr);
      int fd = accept4(
          m_fd, reinterpret_cast<sockaddr *>(&addr), &addrLen, SOCK_NONBLOCK
      );

      if (fd == -1) {
        if (errno == EAGAIN)
          return;
        m_throwError(AcceptException());
        return;
      }

      auto client = Client(fd, addr.sin_addr);
      m_clients.emplace(fd, std::move(client));

      // client gets destroyed here
      //
      // I also tried to do
      // m_clients.emplace(fd, Client(fd, addr.sin_addr))
      // but the client also gets destroyed immediately
      // what I want to do is being able to insert a new Client
      // into the map without having to implement copy semantics for it
      // because it doesn't make sense to have them in this case
    }
    int m_fd;
c++ class oop containers move
2个回答
0
投票

一方面,您错误地使用了

emplace
:如果您只是
std::move
一个现有对象,则实际上并不需要
emplace

但是,回到你的问题:

std::move
不会移动“所有权”,它会移动数据。仍然涉及两个对象(移出的对象和移至的对象),因此您的临时
client
被破坏。


0
投票

client
正在移动,只是所有对象在函数结束时都被销毁,并且
client
在函数中声明了。

如果你不希望这种情况发生,你可以做的就是使用

std::piecewise_construct
标记的
emplace
重载直接构造地图中的对象,而不是像

void m_acceptClient() {
  sockaddr_in addr;
  socklen_t addrLen = sizeof(addr);
  int fd = accept4(
      m_fd, reinterpret_cast<sockaddr *>(&addr), &addrLen, SOCK_NONBLOCK
  );

  if (fd == -1) {
    if (errno == EAGAIN)
      return;
    m_throwError(AcceptException());
    return;
  }

  auto client = Client(fd, addr.sin_addr);
  m_clients.emplace(std::piecewise_construct, 
                    std::forward_as_tuple(fd), 
                    std::forward_as_tuple(fd, addr.sin_addr));
}
    ```
© www.soinside.com 2019 - 2024. All rights reserved.