在做一个处理图论的项目时,我使用了这样的对象:
class Node{
vector<Node> nodeList;
};
Node n = new Node();
Node a = new Node();
n.nodeList.push_back(a);
创建了大约20个节点,每个节点平均有3个连接到其他节点,我的程序基本上会挂起。
为了解决这个问题,我将对象声明更改为
class Node{
vector<Node*> nodeList;
};
Node* n = new Node();
Node* a = new Node();
n.nodeList.push_back(a);
我的程序通过10个连接立即运行50个节点。
第二个例子运行得更快,因为我只是添加指向列表的指针,而不是实际的节点,对吧?
但是C ++文档说new
关键字返回指向创建对象的指针。为什么在第一个例子中将整个对象放入向量而不仅仅是指针?
C ++中的标准是否有理由将整个对象复制到数据结构而不是指针?
编辑: 我道歉,你是对的第一个例子不应该编译。我的驱动器上不再有第一个例子了,我不记得究竟是怎么回事。遗憾。
答案 0 :(得分:3)
C ++中的标准是否有理由将整个对象复制到数据结构而不是指针?
传统上,所有标准库容器类都使用值语义而不是引用语义。
值语义意味着容器创建其元素的内部副本并返回这些元素的副本,而Reference Semantics意味着容器包含对作为其元素的对象的引用。通过使用指针作为容器元素实现此目的的最明显方法。标准库使用值语义,因为:
您展示的第一个代码示例无法正常工作。使用new
强制指针。因为这个指针需要指向freestore上的对象。具有非指针数据类型的对象不能这样做。或许,您在代码中所拥有的是将派生类对象分配给基类对象,从而产生 Object slicing 。
如果确实需要引用语义,最好使用 smart pointer 作为容器元素,而不是现在使用的原始指针。
答案 1 :(得分:1)
但是C ++文档说new关键字返回一个指针 到创建的对象。为什么将整个对象放入向量中 第一个例子而不仅仅是指针?
它没有,这段代码:
class Node{
vector<Node> nodeList;
};
Node n = new Node();
Node a = new Node();
n.nodeList.push_back(a);
根本不会编译,你不能指向一个值或引用变量的指针。
向量将保存您在模板参数中指定的内容,是指针或整个对象(byVal):
vector<Node> nodeList;
此向量将是Node对象的集合(按值),您只能按值推回Node对象。
vector<Node*> nodeList;
这是一个Node类型的指针向量,你只能推回类型为node的指针。
答案 2 :(得分:1)
但是C ++文档说
new
关键字返回指向创建对象的指针。为什么在第一个例子中将整个对象放入向量而不仅仅是指针?
可能不是...... Node a = new Node();
可以编译的唯一方法是,如果有Node(Node*)
或Node(const Node*)
构造函数,Steven可能会在给出评论后告诉我们。
所以 - 我最近的SO口头禅 - “向我们展示代码或它没有发生”。 ;-P
C ++中的标准是否有理由将整个对象复制到数据结构而不是指针?
容器被设计为具有值语义。这非常灵活,因为如果适合您的目的,您可以选择在容器中包含原始或任意多个智能指针。如果容器被设计为提取和存储指向push_back()
对象的原始指针,则会有更多的决策和必要的低效率。例如,double
或int
s的容器不希望将每个容器间接存储在单独的(非连续的)堆内存中 - 这会对性能造成很大影响。