复制指针向量的构造函数

时间:2016-05-07 19:48:39

标签: c++ pointers vector

我试图创建一个包含指针向量的节点类。这是我的代码:

node.h:

#ifndef NODE_H
#define NODE_H

class node
{
public:
    vector<node*> next;
    void add_arc(node & a)

    string some_string;

#endif

node.cpp:

void node::add_arc(node & a)
{
    node *b = &a;
    next.push_back(b);       //only copyies nodes
}

main.cpp中:

int main()
{
    vector<node> nodes;
    node a;
    node b;
    node c;

    a.somestring = "a";
    b.somestring = "b";
    c.somestring = "c";



    a.add_arc(b);      //a should point to b
    a.add_arc(c);      //a should point to c

    nodes.push_back(a);
    nodes.push_back(b);
    nodes.push_back(c);

    cout << nodes[0].next.size() << endl;           // prints "2", works fine
    cout << nodes[0].next[0]->some_string << endl;  //empty
}

我认为这就像重载push_back一样简单:

void push_back(vertex * pointer)
{
    next.push_back(pointer);
}

但我认为我真的需要一个复制构造函数或其他方法才能使其工作。我如何为指针向量做这个?

编辑:我想我没有解释清楚。看看这个问题的答案: Segmentation fault when accessing a pointer's member function in a vector 制作&#39; a&#39;引用对我不起作用

1 个答案:

答案 0 :(得分:1)

它有效......

您的代码按预期生成正确的输出(请参阅online demo):

2
b

......然而,这种设计不是未来的证据

然而,这个结果与运气有某种关系,因为在你的代码片段中:

  • nodes向量中的节点是原始对象的副本,包括其所有指针
  • 这些指针指向的本地对象a,b,c仍然存在

然而,在更复杂的代码中,您很快会以悬空指针结束。 想象一下:

  • 错误示例1:您创建一个图表,将所有节点直接保存在节点向量中。然后,在节点之间添加第一个弧。只要您向向量添加新节点,就可能会发生重新分配,并且您有可能看到所有next指针无效。
  • 错误示例2:您初始化了一个图形,但是在main调用的函数中。在这种情况下,只要从此函数返回,所有本地节点都将被销毁,并且向量的节点将指向不再存在的对象。 UB保证!

如何改善?

您的设计无法识别节点都属于同一图表。

快速而肮脏的出路:始终从免费商店创建节点,并将其存储在vector<node*>中。

vector<node*> nodes;
node *a = new node("a");  // Imagine a node constructor 
node *b = new node("b");
a->add_arc(b);            //change signature, to accept a pointer 
nodes.push_back(a);
nodes.push_back(b);

有一个更好的方法:进一步改进以前的方法,但使用shared_ptr<node*>来确保不再引用的节点(既不是节点向量,也不是由弧线)自动销毁。

还有一种更好的方法:将节点封装在表示图形的类中。在这种情况下,您可以考虑使用vector<nodes>并使用向量中目标节点的索引替换next中的指针。没有指针,但完美的图形副本将更容易。没有更多的内存管理麻烦。

class node    // just to give the general idea
{
public:
    vector<int> next;  // not usable without the graph 
    void add_arc(int a)
    string id;
};

class graph {
    vector<node> nodes; 
public:  
    void add_node (node a);  
    void add_arc (string from, string to);  
    node& operator[] (size_t i); 
    ...
};