C++ 如何在c++;上课?

C++ 如何在c++;上课?,c++,c++11,pointers,smart-pointers,C++,C++11,Pointers,Smart Pointers,我有一个类节点,它必须有一个输入边的列表。然而,这些输入边缘,并不意味着由节点修改,仅可访问。有人建议我为此使用智能指针,如下所示: class Node { private: std::vector<std::unique_ptr<Edge>> inEdges; //... public: void inline AddEdge(std::unique_ptr<Edge>& edge) // could be const here t

我有一个类
节点
,它必须有一个输入边的列表。然而,这些输入
边缘
,并不意味着由
节点
修改,仅可访问。有人建议我为此使用智能指针,如下所示:

class Node
{
private:
    std::vector<std::unique_ptr<Edge>> inEdges;
//...
public:
    void inline AddEdge(std::unique_ptr<Edge>& edge) // could be const here too
    {
        this->inEdges.push_back(edge);
    }
//...
}
class Edge
{
    class Node* a;
    class Node* b;
    double w;

public:
    Edge(Node* a, Node* b, double w): a(a), b(b), w(w) {}
};

class Node
{
private:
    double x, y, z;
    std::vector<Edge*> inEdges;

public:
    Node(double x, double y, double z): x(x), y(y), z(z) {}

    void AddEdge(Edge* edge)
    {
        this->inEdges.push_back(edge);
    }
};

int main()
{
    std::vector<Node> nodes; // values, not pointers
    std::vector<Edge> edges;

    // NOTE: You MUST create ALL of the Nodes BEFORE
    // adding their pointers to the Edges and you must
    // create ALL the Edges BEFORE adding their pointers
    // to the Nodes because resizing the vectors will
    // INVALIDATE all the pointers

    // FIRST create ALL the nodes
    nodes.emplace_back(0, 0.5, 0.0); // make nodes[0]
    nodes.emplace_back(1, 0.5, 0.0); // make nodes[1]

    // NEXT create ALL the edges
    edges.emplace_back(&nodes[0], &nodes[1], 1.0); // make edges[0]

    // Finally add the edges to the nodes
    nodes[1].AddEdge(&edges[0]);

}
类节点
{
私人:
向量不等式;
//...
公众:
void inline AddEdge(std::unique_ptr&edge)//这里也可以是常量
{
这->边缘。向后推(边缘);
}
//...
}
因此,在运行时,我可以创建节点和边的列表,并为每个节点指定边:

int main()
{
    std::vector<std::unique_ptr<Nodes>> nodes;
    std::vector<std::unique_ptr<Edges>> edges;
    nodes.push_back(std::make_unique<Node>(0, 0.5, 0.0));
    nodes.push_back(std::make_unique<Node>(1, 0.5, 0.0));
    edges.push_back(std::make_unique<Edge>(*nodes[0], *nodes[1], 1.0));
    nodes[1]->AddEdge(edges[0]);
}
intmain()
{
std::向量节点;
向量边;
nodes.push_back(std::make_unique(0,0.5,0.0));
nodes.push_back(std::make_unique(1,0.5,0.0));
edges.push_back(std::make_unique(*节点[0],*节点[1],1.0));
节点[1]->AddEdge(边[0]);
}
编译器给出了错误

错误1错误C2280:'std::unique\u ptr>::unique\u ptr(const std::unique\u ptr&'):尝试引用已删除的函数c:\program files(x86)\microsoft visual studio 12.0\vc\include\xmemory0 593 1 sirs

它用于处理
节点
std::vector
内的原始指针,因为
AddEdge
的签名将是
void AddEdge(Edge&Edge)
,在向量内向后推
&edge

我的代码有什么问题?我应该如何着手纠正它?鉴于
std::vector
无法存储引用,因为这些引用是不可分配的


PS:我不想将指针的所有权转移到
节点
对象…

std::vector::push_back
复制它的参数,并且
std::unique_ptr
不能复制,只能移动它

您必须移动传递的
std::unique\u ptr

void inline AddEdge(std::unique_ptr<Edge> edge)
{
    this->inEdges.push_back(std::move(edge));
}

另外,
inEdges
不必是
std::unique_ptr
的向量,因为它们应该是非所有的。
std::unique_ptr
意味着所有权,但正如您所说,
节点不拥有
边缘

改为使用
std::vector
(或者在不久的将来实现时使用
std::observer_ptr
),因为原始指针(通常)意味着非所有权。您只需小心
std::vector
的生存期不超过
std::unique_ptr
s的生存期,否则指针将悬空。

您应该只移动
std::unique_ptr
的实例,以便将它们放入
std::vector
。否则您需要
std::shared\u ptr

class Node
{
private:
    std::vector<std::unique_ptr<Edge>> inEdges;
//...
public:
    void AddEdge(std::unique_ptr<Edge>&& edge)
    {
        inEdges.push_back(std::move(edge));
    }
//...
}
或:

node.AddEdge(std::make_unique(/*args*/);
作为旁白。如果您确实发现您正在通过引用传递
std::unique\u ptr
,那么这可能是您应该使用
std::shared\u ptr
的标志


另外,
inline
在类内声明的方法上是多余的。

您试图将std::unique\u ptr的副本推送到向量中。该向量正试图创建唯一的_ptr副本,这是不允许的,因为它会破坏唯一所有权的目的

您首先应该考虑哪个对象拥有哪个对象,并且仅使用<强> STD::UnQuyJPTR <强>如果确实有唯一所有权的情况。< /P> 您可以做以下几件事:

  • std::move()将指针插入向量,这将导致上一个副本无效(请参阅:移动语义)
  • 如果希望多个对象保存指针的副本,请使用std::shared_ptr。因为看起来您想要指针的多个副本,所以这可能是您想要的方向
  • 在您的案例中,阅读std::weak_ptr可能是值得的,因为我认为您可能希望对象相互引用,而不创建循环引用。弱指针在共享_ptr上工作而不实际增加引用计数,并且在某些情况下非常重要,因为您希望确保对象不会在引用上挂起太长时间并导致内存泄漏

    希望这能有所帮助。

    我不会为此使用智能指针。我认为最简单的方法是将所有节点和边作为值存储在主向量中,然后使用原始指针来表示它们之间的关系

    您不需要智能指针,因为向量管理节点和边的生存期和销毁,所以不需要其他任何东西来拥有它们

    使用此方案要记住的最重要的一点是,在创建使用指向向量元素的指针的数据结构后,必须绝不更改向量的大小

    原因是更改向量的大小会使所有指针失效(对象可能会移动到不同的内存位置)

    比如说:

    class Node
    {
    private:
        std::vector<std::unique_ptr<Edge>> inEdges;
    //...
    public:
        void inline AddEdge(std::unique_ptr<Edge>& edge) // could be const here too
        {
            this->inEdges.push_back(edge);
        }
    //...
    }
    
    class Edge
    {
        class Node* a;
        class Node* b;
        double w;
    
    public:
        Edge(Node* a, Node* b, double w): a(a), b(b), w(w) {}
    };
    
    class Node
    {
    private:
        double x, y, z;
        std::vector<Edge*> inEdges;
    
    public:
        Node(double x, double y, double z): x(x), y(y), z(z) {}
    
        void AddEdge(Edge* edge)
        {
            this->inEdges.push_back(edge);
        }
    };
    
    int main()
    {
        std::vector<Node> nodes; // values, not pointers
        std::vector<Edge> edges;
    
        // NOTE: You MUST create ALL of the Nodes BEFORE
        // adding their pointers to the Edges and you must
        // create ALL the Edges BEFORE adding their pointers
        // to the Nodes because resizing the vectors will
        // INVALIDATE all the pointers
    
        // FIRST create ALL the nodes
        nodes.emplace_back(0, 0.5, 0.0); // make nodes[0]
        nodes.emplace_back(1, 0.5, 0.0); // make nodes[1]
    
        // NEXT create ALL the edges
        edges.emplace_back(&nodes[0], &nodes[1], 1.0); // make edges[0]
    
        // Finally add the edges to the nodes
        nodes[1].AddEdge(&edges[0]);
    
    }
    
    类边缘
    {
    类节点*a;
    类节点*b;
    双w;
    公众:
    边(节点*a,节点*b,双w):a(a),b(b),w(w){}
    };
    类节点
    {
    私人:
    双x,y,z;
    向量不等式;
    公众:
    节点(双x,双y,双z):x(x),y(y),z(z){
    无效附加边(边*边)
    {
    这->边缘。向后推(边缘);
    }
    };
    int main()
    {
    std::vector nodes;//值,而不是指针
    向量边;
    //注意:必须在创建之前创建所有节点
    //将它们的指针添加到边,您必须
    //在添加其指针之前创建所有边
    //因为调整向量的大小将
    //使所有指针无效
    //首先创建所有节点
    nodes.emplace_back(0,0.5,0.0);//生成节点[0]
    nodes.emplace_back(1,0.5,0.0);//生成节点[1]
    //接下来创建所有边
    edges.emplace_back(&nodes[0],&nodes[1],1.0);//生成边[0]
    //最后,将边添加到节点
    节点[1]。添加边(&边[0]);
    }
    
    
    
    class Edge
    {
        class Node* a;
        class Node* b;
        double w;
    
    public:
        Edge(Node* a, Node* b, double w): a(a), b(b), w(w) {}
    };
    
    class Node
    {
    private:
        double x, y, z;
        std::vector<Edge*> inEdges;
    
    public:
        Node(double x, double y, double z): x(x), y(y), z(z) {}
    
        void AddEdge(Edge* edge)
        {
            this->inEdges.push_back(edge);
        }
    };
    
    int main()
    {
        std::vector<Node> nodes; // values, not pointers
        std::vector<Edge> edges;
    
        // NOTE: You MUST create ALL of the Nodes BEFORE
        // adding their pointers to the Edges and you must
        // create ALL the Edges BEFORE adding their pointers
        // to the Nodes because resizing the vectors will
        // INVALIDATE all the pointers
    
        // FIRST create ALL the nodes
        nodes.emplace_back(0, 0.5, 0.0); // make nodes[0]
        nodes.emplace_back(1, 0.5, 0.0); // make nodes[1]
    
        // NEXT create ALL the edges
        edges.emplace_back(&nodes[0], &nodes[1], 1.0); // make edges[0]
    
        // Finally add the edges to the nodes
        nodes[1].AddEdge(&edges[0]);
    
    }