连接两个对象的合理方式
A sensible way of linking two objects
我有两个对象向量:
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
此外,在这些向量上创建辅助包装器也是高度可维护和可扩展的
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 准确了解对象在内存中的映射方式
- 为什么两种不同的对象初始化方式给出不同的输出
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- 我试图创建临时对象的方式有错误吗
- 如何以编程方式区分在内存的堆和堆栈部分创建的对象
- 为什么Visual Studio会以不同的方式对待我的对象
- 在地图上启动对象的正确方式
- 处理无法按预期方式创建的对象,c++
- 我需要帮助以连续的方式将对象的字段正确写入文件
- 以支持继承的方式将自身shared_ptr添加到对象构造函数中的向量中
- 如何设计对象以不同方式设置文本格式
- 临时对象在 C++ 中的行为方式?
- Sizeof 舍入到对齐方式,但编译器仍将对象放在剩余的字节中
- 自动热键:重新映射 MS Visio 的快捷方式,以将手动选择的对象对齐到顶部(好像按:"AlignTop")
- 以面向对象的方式解析自定义数据包
- 重载小于 (<) 运算符,用于以多种方式对对象进行排序
- 在 OpenGL 中渲染对象的哪种方式更有效
- 在c++中存储一个对象或不存储对象的首选方式是什么
- 在C 中以通用方式构建对象,设置字段并返回对象