问题
Let me start by stating I am using a GNU C++ compiler that does NOT support move constructors. It only supports the 98 standard.
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;
}
}
};
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);
}
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.
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.)
回答1:
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.
回答2:
If you could use Smart Pointers Boost library, store your class inside a shared_ptr as in:
std::vector<boost::shared_ptr<SimpleSocket>>
来源:https://stackoverflow.com/questions/42281711/raii-berkeley-sockets-and-stl-containers