我有一个类,既不实现默认构造函数,也不实现复制构造函数,只实现移动构造函数,并且在函数内部我想将此类的新实例插入 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;
一方面,您错误地使用了
emplace
:如果您只是 std::move
一个现有对象,则实际上并不需要 emplace
。
但是,回到你的问题:
std::move
不会移动“所有权”,它会移动数据。仍然涉及两个对象(移出的对象和移至的对象),因此您的临时 client
被破坏。
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));
}
```