我在想一个管理我的TCP连接的C++类(在Linux上).在销毁时,应该关闭连接,类似于:
TCPConnection::~TCPConnection()
{
close(_socket);
}
Run Code Online (Sandbox Code Playgroud)
问题是,当把这个类的对象放到例如一个向量中时,连接也会像这样关闭,即使我仍然想要使用连接.我怎么解决这个问题?总的来说这是个坏主意吗?
你想要实现的是一个名为RAII的设计模式,所以一旦你的TCPConnection被实例化,它就会获取资源,一旦它被销毁它就会释放资源.如果它被销毁,则意味着程序员的意图是停止使用这些资源.如果您仍然需要使用它们,那么您必须延长对象的使用寿命.您可以使用typedef std::shared_ptr<TCPConnection> TCPConnectionPtr,然后可以将TCPConnectionPtr实例放在许多位置,只有在所有这些实例都被销毁后才会关闭连接.
示例代码(http://coliru.stacked-crooked.com/a/581a856ee32890d2):
#include <iostream>
#include <vector>
#include <memory>
class TCPConnection {
int inst;
static int inst_count;
public:
TCPConnection() { inst=inst_count++; std::cout << "TCPConnection created: " << inst << std::endl; }
~TCPConnection() { std::cout << "TCPConnection destroyed:" << inst << std::endl; }
};
int TCPConnection::inst_count;
// version if If c++11 is available, can be also implemented with boost::shared_ptr
// Removing individual TCPConnection from vector will also decrement its shared_ptr
// usage count and if it is zero then will destroy also such connections.
typedef std::shared_ptr<TCPConnection> TCPConnectionPtr;
typedef std::vector<TCPConnectionPtr> TCPConnectionPtrVec;
void fun1() {
TCPConnectionPtrVec vec;
vec.push_back(TCPConnectionPtr(new TCPConnection()));
}
// version for pre c++11 compiler, but I would recomend using boost::shared_ptr
// Class TCPConnectionsVecWrapper is a helper to make sure connections are safely freed.
class TCPConnectionsVecWrapper {
// No copying allowed
TCPConnectionsVecWrapper( const TCPConnectionsVecWrapper& );
TCPConnectionsVecWrapper& operator=( const TCPConnectionsVecWrapper& );
typedef std::vector<TCPConnection*> TCPConnectionPtrsVec;
TCPConnectionPtrsVec vec;
public:
TCPConnectionsVecWrapper() {}
~TCPConnectionsVecWrapper() {
for (TCPConnectionPtrsVec::const_iterator itr = vec.begin(); itr != vec.end(); ++itr) delete *itr;
}
TCPConnection* createConnection() {
vec.push_back(new TCPConnection());
return vec.back();
}
void remove(int index) {
delete vec[index];
vec.erase(vec.begin() + index);
}
TCPConnection* get(int index) { return vec[index]; }
const TCPConnection* get(int index) const { return vec[index]; }
std::size_t size() const { return vec.size(); }
};
void fun2() {
// All TCPConnection will get deleted once tcpConnectionsWrapper is out of scope
TCPConnectionsVecWrapper conns;
TCPConnection* con1 = conns.createConnection();
(void)con1; // unused
TCPConnection* con2 = conns.createConnection();
(void)con2; // unused
for ( size_t i = 0; i < conns.size(); ++i ) {
TCPConnection* con = conns.get(i);
(void)con; // unused
}
conns.remove(0);
}
int main(int argc, char** argv){
fun1();
fun2();
}
Run Code Online (Sandbox Code Playgroud)