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]);
}