在C++中关闭析构函数中的连接

Ses*_*shu 2 c++ networking

我在想一个管理我的TCP连接的C++类(在Linux上).在销毁时,应该关闭连接,类似于:

TCPConnection::~TCPConnection()
{
  close(_socket);
}
Run Code Online (Sandbox Code Playgroud)

问题是,当把这个类的对象放到例如一个向量中时,连接也会像这样关闭,即使我仍然想要使用连接.我怎么解决这个问题?总的来说这是个坏主意吗?

mar*_*inj 7

你想要实现的是一个名为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)