两个类之间的循环引用
Circular references between two classes
我知道这一定是一个 n00b 问题,但我必须实现一个模型客户端-服务器顺序交互应用程序,并且由于客户端-服务器调用的数量各不相同,我不能只是迭代外部函数中的步骤,总是从客户端获取数据,然后将其转发到服务器,反之亦然,所以我需要让我的 Server
和 Client
类相互了解,以便它们可以调用它们的他们之间的公共方法。一种方法是将两者设计为单例,但我希望以更简单的方式做到这一点,更准确地说是使用循环引用:客户端存储对服务器的引用,服务器存储对客户端的引用。我知道这可能不是一个好方法,当调用堆栈变得太深时,它可能会导致调用堆栈爆炸,因此欢迎对我的设计进行任何改进。
为了实现所描述的实现,我认为我可以使用 std::shared_ptr
,因为如果我还想防止两个变量在调用两个 setter 时被破坏,std::unique_ptr
不起作用(对吗?所以,这就是我所拥有的(简化代码):
#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;
}
不幸的是,我的代码似乎尝试多次调用客户端和服务器(隐式)析构函数,或者一些类似的讨厌的事情,我确信这是由于我对std::shared_ptr
应该如何工作的理解不足造成的。请指教。
您在堆栈上分配服务器和客户端实例,当main()
退出时,它们将被删除。您也不想std::shared_ptr
删除它们。因此,有两种解决方案:
-
在客户端和服务器中使用非托管指针,并在外部管理其生存期。
-
在任何地方使用托管指针,包括
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;
}
您的变量具有自动生存期,当它们超出范围时将被销毁。
因此,使用任何生存期管理的智能指针都是错误的,因为它将再次调用 delete。
- 基于范围的 for 循环range_declaration中各种说明符之间的性能差异
- 当数组位于两个循环之间时,您可以调用数组的 void 函数吗?
- 为什么 for 循环和 while 循环之间的 continue 不同?
- C++ 中的类之间的数据重新循环 - 错误:'<class name>'未在此范围内声明
- C++ if 语句将条件设置为 true 和循环中的 OR-ing 条件之间的行为差异
- pthread_yield无法在线程之间正确循环
- matlab 和 c++ 中的 while 循环之间的区别
- 我是否应该避免在循环中的常数之间进行操作
- 在 C 中并行化嵌套循环的几种方法之间的差异,C++使用 OpenMP
- 符号和未签名整数表达式之间的比较,以进行循环误差
- OPENCV MAT问题:直方图和此循环之间的差异
- 三个数字之间的 C++ 相加两个更高的数字,没有循环和数组
- 开放MP;嵌套循环之间的操作
- 本应生成 2 个介于 1 和 9 之间的随机数的程序C++只生成 6 和 9 并且没有正确循环
- OpenMP 嵌套循环,每个"for"循环之间都有代码
- 在基于范围的 for 循环中,& 和 && 之间有什么区别?
- 逗号(,)在条件部分中两个表达式之间的for循环中的工作方式
- 使用嵌入循环查找1-239之间的素数
- 有没有一种方法可以在变量之间循环?(C++)
- 应用程序中库之间循环依赖的影响