首先声明我使用的是不支持移动构造函数的 GNU C++ 编译器。它只支持98标准。
鉴于此,我想编写一个 C++ 类,以遵循 RAII 的简单方式包装 Berkeley 风格的套接字。这是一个非常简单的类:
class SimpleSocket
{
int m_sockfd;
public:
SimpleSocket()
{
m_sockfd = socket(AF_INET, ...);
}
SimpleSocket(const SimpleSocket& other)
{
m_sockfd = other.m_sockfd;
}
~SimpleSocket()
{
closeSocket();
}
void closeSocket()
{
if(m_sockfd != -1)
{
close(m_sockfd);
m_sockfd = -1;
}
}
};
假设我想像这样在 STL C++ vector 中创建一大堆这些内容。
vector<SimpleSocket> vec_of_sockets;
for(int i = 0 ; i < 10 ; ++i)
{
SimpleSocket new_sock;
vec_of_sockets.push_back(new_sock);
}
我发现 vector 使用复制构造函数来移动对象,然后销毁旧套接字。这具有调用 closeSocket() 的不幸副作用,它关闭了我的文件描述符。
我想遵循 RAII 并在调用对象的析构函数时关闭文件描述符,但它使我无法在 STL C++ 容器内使用它。我知道我可以更新我的编译器并实现一个可以解决问题的移动构造函数,但我在一家不相信使用任何现代东西的公司工作。 (我真的很沮丧,但我对此无能为力。)
最佳答案
Linux 和 Windows 都在内核/winsock2 级别实现引用计数。您可以在用户模式程序中使用引用计数指针,但这会浪费比您想象的更多的内存。您可以提升操作系统已经在幕后执行的引用计数。这是 Linux 的示例实现:
SimpleSocket(const SimpleSocket& other)
{
m_sockfd = dup(other.m_sockfd);
}
操作系统将增加指定套接字的引用计数,并返回一个新的描述符供您使用。请注意,当您以这种方式“复制”套接字时,即使描述符不同,这两个套接字都将引用相同的底层套接字。
关于c++ - RAII、伯克利套接字和 STL 容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42281711/