我正在构建一棵树,我有一个类Node,它包含两个或三个整数、一个向量和一个指针。向量存储Node实例,如下所示-将Node命名为A
class A {
public:
A(A *parent) :
_parent(parent) {
}
std::vector<INSTANCES_OF_A> v;
private:
A *_parent;
};我确实可以使用:
class A {
public:
A(A *parent) :
_parent(parent) {
}
std::vector<A *> v;
private:
A *_parent;
};
// Insertion
A a;
a.v.push_back(new A(&a));或者:
class A {
public:
A(A *parent) :
_parent(parent) {
}
std::vector<A> v;
private:
A *_parent;
};
// Insertion
A a(NULL);
a.v.push_back(A(&a));在第一种情况下,除了实例本身,我将为指向A的每个指针分配额外的4~8个字节。
在第二种情况下,将保存这4~8个字节,但下面的场景配置如下:
a.v.push_back(A(&a))向后推--我想是动态分配--从A(&a)构建的实例;A的每个实例时构建的地址的关联-- A *_parent成员。制动器
问题
有没有办法解决这个悬垂的指针问题,尊重这两个约束?或者,是否有更好的方法来解决这个问题?
发布于 2013-03-15 20:12:32
我们不知道您计划如何处理您的A对象,以及它们是否相对较大。例如,如果它们可以链接在一起(通过存在于另一个A的A向量中),那么第二个选择是个坏主意。如果您的A类包含多个成员,而且如果他们在内存中非常饥饿,这也是个坏主意。正如您所指出的,这可能导致向量大小移动大量数据。最重要的是,您的信息可能是多余的,因为有不同的A实例,成员绝对平等。
我倾向于通过存储指向A实例的指针或引用来实现第一种方法,但是您必须小心范围。例如,不要添加指针,如下所示:
void inSomeFunc(A& a)
{
A b(NULL); // consider using nullptr if you can compile in C++11
a.v.push_back(&b); // pushing the memory address of local variable 'b'
} // b goes out of scope, so the &b in a.v becomes invalid在这种情况下,如果尝试访问添加在v中的元素,则可能会出现运行时错误。
也许给出更准确的信息,你的目标,以一个更具体的答案。
提供附加信息的编辑:
构建树的通常方法(特别是有n个子节点)是存储指向子节点的指针。也许您可以直接存储节点,而不是指针,如果您有一个静态树(构建一次,从不修改后:只读)。尽管如此,如果你有大量的孩子,那么它最终将需要做大量的向量调整工作。
除了特定的情况外,拥有一个常量树并不那么有用,所以最好的方法就是存储指向节点的指针。这使得修改树的速度快得多(只需管理从向量中添加和删除指针),并且与管理对象一样简单。你唯一需要关心的就是内存处理。您的节点必须在堆上分配,由析构函数解除分配,或者声明为局部变量,您可以确定它们不会超出作用域(而不是重新命令)。
我会这样做:
class A {
public:
A(A *parent) :
_parent(parent) {}
/* This will recursively free all the nodes in your tree but BEWARE :
it would probably not work if you have loops in your tree */
~A()
{
for(int i = 0; i < v.size(); ++i)
if(v[i] != NULL)
delete v[i];
}
void addChild(A *node)
{
v.push_back(node);
}
A* addNewChild()
{
A* a = new A(this);
addChild(a);
return a;
}
// others accessors you need, for example operator[]
private:
A *_parent;
std::vector<A *> v;
};发布于 2013-03-15 20:16:55
请注意,push_back会复制一个对象,所以您push_back编辑到向量的对象的地址对向量没有意义。是的,如果存储内存太少,向量类确实会重新分配内存。一种典型的树方法是存储指针。您可能会发现可能实现自己类型的向量,以便手动重新分配它,从而能够相应地更改所有孩子的父母。
std::vector还存储指向数据的指针,否则将不允许在A中包含vector<A>。所以你有这些“悬空”的指针(对我来说不是悬空的,更多的是多余的)。
还请注意,在内存中移动实际数据可能很费时,而且还会增加内存碎片(如果您关心冗余指针,这对您来说一定很重要)。
如果您正在为内存不是非常有限的非嵌入式系统编程,我建议使用第一种方法,并使用显式指针。否则你会浪费时间的。正常的时间和记忆。
https://stackoverflow.com/questions/15440914
复制相似问题