RAII、伯克利套接字和 STL 容器 [英] RAII, Berkeley Sockets, and STL Containers

查看:29
本文介绍了RAII、伯克利套接字和 STL 容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先声明我使用的是不支持移动构造函数的 GNU C++ 编译器.它只支持 98 标准.

Let me start by stating I am using a GNU C++ compiler that does NOT support move constructors. It only supports the 98 standard.

鉴于此,我想编写一个 C++ 类,该类以遵循 RAII 的简单方式包装 Berkeley 风格的套接字.这是一个非常简单的类:

Given that, I want to write a C++ class that wraps Berkeley style sockets in a simple way that follows RAII. Here is a very simple class:

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++ 向量中创建一大堆这些.

Let's say I want to create a whole bunch of these in a STL C++ vector like so.

vector<SimpleSocket> vec_of_sockets;
for(int i = 0 ; i < 10 ; ++i)
{
  SimpleSocket new_sock;
  vec_of_sockets.push_back(new_sock);
}

我发现 vector 使用复制构造函数来移动对象,然后破坏旧的套接字.这具有调用 closeSocket() 关闭我的文件描述符的不幸副作用.

What I found was that vector uses the copy constructor to move the objects around and then destructing the old sockets. This has the unfortunate side-effect of calling closeSocket() which closes my file descriptor.

我想遵循 RAII 并在调用对象的析构函数时关闭文件描述符,但它使我无法在 STL C++ 容器内使用它.我知道我可以更新我的编译器并实现一个移动构造函数来解决这个问题,但我为一家不相信使用任何现代产品的公司工作.(我真的很沮丧,但我对此无能为力.)

I want to follow RAII and close the file descriptor when the object's destructor is called but it makes it where I cannot use it inside of the STL C++ containers. I know that I can update my compiler and implement a move constructor which would fix the problem but I work for a company that does not believe in using anything that is modern. (I'm really frustrated by it but there is nothing I can do about it.)

推荐答案

Linux 和 Windows 都在内核/winsock2 级别实现了引用计数.您可以在用户模式程序中使用引用计数指针,但这会浪费比您想象的更多的内存.您可以提高操作系统已经在幕后进行的引用计数.这是 Linux 的示例实现:

Both Linux and Windows implement reference counting in the kernel/winsock2 level. you could have used a reference counted pointer in your user mode program, but that would waste more memory than you'd think. you can elevate the reference counting you OS already does behind the scenes. here is an example implementation for Linux:

 SimpleSocket(const SimpleSocket& other)
  {
    m_sockfd = dup(other.m_sockfd);
  }

操作系统将增加指定套接字的引用计数,并返回一个您可以使用的新描述符.请注意,当您以这种方式复制"套接字时,即使描述符不同,这两个套接字也将引用相同的底层套接字.

The operating system will increment the reference count of the specified socket and will return a new descriptor in which you can use. do note that when you "copy" a socket this way, both of the sockets will refer to the same underlying socket even if the descriptors are different.

这篇关于RAII、伯克利套接字和 STL 容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆