两个类之间的循环引用

Mih*_*dor 5 c++ pointers client-server pass-by-reference circular-reference

我知道这必须是一个n00b问题,但我必须实现一个模型客户端 - 服务器顺序交互应用程序,并且因为客户端 - 服务器调用的数量不同,我不能只是迭代外部函数中的步骤,总是从中获取数据客户端,然后将其转发到服务器,反之亦然,所以我需要让我Server和我们Client相互了解,以便他们可以在自己之间调用他们的公共方法.一种方法是将两者都设计为单身,但我希望以更简单的方式进行,更准确地说使用循环引用:客户端存储对服务器的引用,服务器存储对客户端的引用.我知道这可能不是一个好方法,并且当它变得太深时它可能导致调用堆栈爆炸,因此欢迎对我的设计进行任何改进.

为了实现所描述的实现,我认为我可以使用std::shared_ptr,因为std::unique_ptr当我调用两个setter时,如果我还想阻止main中的两个变量被破坏,那么它将无法工作(对吗?).所以,这就是我所拥有的(简化代码):

#include <iostream>
#include <memory>

class Server;

class Client
{
public:
    void SetServer (const Server &server);
private:
    std::shared_ptr<const Server> server;
};

void Client::SetServer (const Server &server)
{
    this->server = std::shared_ptr<const Server>(&server);
}

class Server
{
public:
    void SetClient (const Client &client);
private:
    std::shared_ptr<const Client> client;
};

void Server::SetClient (const Client &client)
{
    this->client = std::shared_ptr<const Client>(&client);
}

int main ()
{
    Server server;
    Client client;

    server.SetClient(client);
    client.SetServer(server);

    //Here I ask the client to start interacting with the server.
    //The process will terminate once the client
    //exhausts all the data it needs to send to the server for processing

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我的代码似乎试图多次调用Client和Server(隐式)析构函数,或者类似讨厌的东西,我确信这是由于我对如何std::shared_ptr工作的理解不足造成的.请指教.

Rei*_*ica 7

您在堆栈上分配服务器和客户端实例,main()退出时将删除它们.您也不想std::shared_ptr删除它们.因此,有两种解决方案:

  1. 在客户端和服务器中使用非托管指针,并在外部管理其生命周期.

  2. 在任何地方使用托管指针,包括main().注意这shared_ptr意味着所有权.在当前设计中,服务器拥有客户端,但客户端拥有服务器.这是一个循环引用:默认情况下,它们永远不会被释放,除非你仍然可以重置其中一个指针.

    例如,您可以确定客户端使服务器保持活动状态,因此如果没有其他shared_ptrs指向它,则最后消失的客户端将关闭服务器.服务器将拥有一个weak_ptr客户端,但客户端将拥有一个shared_ptr服务器.

class Client;
class Server;

class Client
{
public:
    void SetServer (const std::shared_ptr<const Server> &server);
private:
    std::shared_ptr<const Server> server;
};

void Client::SetServer (const std::shared_ptr<const Server> &server)
{
    this->server = server;
}

class Server
{
public:
    void SetClient (const std::weak_ptr<const Client> &client);
private:
    std::weak_ptr<const Client> client;
};

void Server::SetClient (const std::weak_ptr<const Client> &client)
{
    this->client = client;
}


int main()
{
  std::shared_ptr<Server> server(new Server);
  std::shared_ptr<Client> client(new Client);

  server->SetClient(client);
  client->SetServer(server);

  // do stuff

  return 0;
}
Run Code Online (Sandbox Code Playgroud)