使用共享指针在 C++ 中对网络建模是否是明智的设计?

Is modelling a Network in C++ with shared pointers a sane design?

我目前正在扩展我的 C++ 知识。为此,我正在编写一个模板网络。 (实际练习是Project Euler's problem 107,如果有人感兴趣的话。)

现在阅读 C++11 中的指针,我的 class 的以下设计看起来很合理:

template< typename T, size_t D >
class Network<T,D>
{
  public:
    Network();
    ~Network();
    bool add_edge( size_t, size_t, T );
    bool remove_edge( size_t, size_t );
    struct Node;
    struct Edge;
  private:
    vector<Node> network;
};

初步实现如下

template< typename T, size_t D >
struct Network<T,D>::Edge
{
  pair<shared_ptr<Node>,shared_ptr<Node>> vertices;
  T weight;
}

template< typename T, size_t D >
struct Network<T,D>::Node
{
  Node( size_t idx )
    index = idx;

  size_t index;
  vector<shared_ptr<Edge>> connections;
};

template< typename T, size_t D >
Network<T,D>::Network( )
{
  network.reserve( D );
  for( size_t s = 0; s <= D; s++ )
    network.push_back( Node(s) );
}

template< typename T, size_t D >
Network<T,D>::~Network() {}

请注意,这只是初步代码;我还没有编译任何东西。

但是,出现了以下问题:

  1. 这是对 std::shared_ptr 的合法使用吗?用它来计算从Edges到Nodes的引用可以很容易地确定一个节点是否是孤立的。
  2. 在我的模型中,是否可以将 std::shared_ptrstd::weak_ptr 交换? 据我了解,没有。在 Edge 中,shared_ptr<Node> 是实际能够计算引用所必需的,在我的 Node 中,shared_ptr<Edge> 是实际保持引用边缘而不丢失它所必需的.

  3. 在较小程度上,使用 size_t D 对我的模板有意义吗? (除了将此模型与多 TB 计算机一起用于解决大型网络的可能性很小......)

  4. 即使这可能会吸引固执己见的答案,我也愿意设计替代方案。

我会说 shared_ptr 或任何其他智能指针在这里都是错误的工具。因为:

  1. 节点和边只有一个明确的所有者:邻接矩阵。将节点存储在数组中(就像您现在所做的那样),并将边存储在矩阵中,均按值存储。共享指针在很难建立所有权时很有用(并且是未经过深思熟虑的设计的症状)。
  2. 将incoming/outgoing条边的个数存储在节点本身,简洁高效
  3. 构造shared_ptr涉及在堆上分配控制块(存储引用计数器和删除器的地方)。 shared_ptr 大小是两个指针的大小。引用计数器维护涉及原子指令,这会在单线程用例中引入不必要的延迟。换句话说,shared_ptr 是可用的最昂贵的指针之一。