连接两个对象的合理方式

A sensible way of linking two objects

本文关键字:方式 对象 两个 连接      更新时间:2023-10-16

我有两个对象向量:

std::vector<Foo*> fooVector; //contains some 100 elements
std::vector<Bar*> barVector; //contains some 10,000 elements

这个想法是,Bar对象永远比Foo对象多得多。但是,每个Foo对象都需要与一个Bar对象相关联;到目前为止,这只需为每个Foo对象提供一个Bar指针和一个getBar()函数即可。

然而,我也需要能够做相反的事情:给定一个Bar对象,我需要一种方法来立即获取其关联的Foo(如果有的话)。实现这一点最简单的方法是给每个Bar一个Foo指针。不过,这似乎是极其多余的,因为我将再引入10000种出错的方法(更不用说其中只有100种是有效的,其余的都是nullptr)。另一种方式,我现在有,是这样的:

Foo* getFooPtr(Bar* barObj){      
for(auto& foo : fooVector){
if(foo->getBar() == barObj)
return foo;
}
}

虽然它有效,但效率很低,因为它每次都必须遍历整个fooVector。此函数需要经常运行,因此这是不可接受的。

我曾考虑过使用类似std::map的东西,但最终仍然存在相同的迭代问题。

[…]到目前为止,这就像给每个Foo对象一个Bar指针和一个getBar()函数一样简单。

在这种情况下,这是:

Foo* getFooPtr(Bar* barObj){      
for(auto& foo : fooVector){
if(foo->getBar() == barObj)
return foo;
}
}

是疯狂。

如果给每个Foo对象一个Bar指针,为什么不给每个Bar一个Foo指针呢?

class Foo
{
protected:
Bar* _bar;
public:
void setBar(Bar* bar);
Bar* getBar() const;
};

class Bar
{
friend class Foo; //allow Foo to set _foo pointer
protected:
Foo* _foo;
public:
Foo* getFoo() const;
};

void Foo::setBar(Bar* bar)
{
this->_bar = bar;
bar->_foo = this;
}
Bar* Foo::getBar() const
{
return this->_bar;
}
Foo* Bar::getFoo() const
{
return this->_foo;
}

每次将Bar对象与Foo对象关联时,两者都会自动保存此关联-您将能够从Foo获取Bar指针,反之亦然:

Foo* f = ...;
f->setBar(...);

现在:

Bar* b = f->getBar();
Foo* bf = b->getFoo();
assert( f == bf ); //This hould always be true

一个包含10000个元素的向量并不是"还有10000种方法会出错"。如果你对所有元素都做同样的操作,这只是出错的另一种方式——填充指针数据的代码。

在没有更好的方法的情况下,我会采用双重链接,只有当我对问题有更广泛的看法时,我才能设计这种方法。从更广泛的角度来看,可能会有更好的选择,可能涉及集合和映射——尤其是如果你需要密集搜索一个酒吧的foo和一个foo的酒吧。

将指针设置封装在一个函数中,该函数可以确保指针对的一致性,并且您是安全的。

特别是,你应该尝试这个选项,看看它是否会给你带来特定的问题。StackOverflow将在这里解决这些问题。

你可以修复错误,但你不能修复由于害怕出错而尚未编写的代码。

如果您不太关心空间复杂性,而时间复杂性是您主要关心的问题,那么您可能需要实现一个哈希表。

查找将是O(1),因为您将没有bucket,并且与存储10.000个指针(无论它们是否为null)相比,您可能会使用更少的内存。

如果需要减少冗余,请创建另一个矢量

std::vector<std::pair<Bar *, Foo *> > barFooVector

这将用作bar到Foo的100种情况的反向映射。

为了确保您不会在指针内纠缠,使用std::shared_ptr而不是裸指针更安全

std::vector<std::shared_ptr<Foo>> fooVector; //contains some 100 elements
std::vector<std::shared_ptr<Bar>> barVector; //contains some 10,000 elements
std::vector<std::pair<std::shared_ptr<Bar>, std::shared_ptr<Foo>> > barFooVector
std::vector<std::pair<std::shared_ptr<Foo>, std::shared_ptr<Bar>> > fooBarVector

此外,在这些向量上创建辅助包装器也是高度可维护和可扩展的