效率不会在你的代码中真正受到影响(向量随机访问的成本基本上没有),你应该关心的是向量数据结构的滥用。
几乎没有理由在类上使用向量来处理如此复杂的事情。具有正确定义接口的类不会使您的代码更有效率,但它将使将来的维护变得更加容易。
您当前的解决方案也可能遇到未定义的行为。以您发布的代码为例:
Block b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
现在,如果pos.a
, pos.b
, pos.c
,引用的向量索引pos.d
不存在于这些向量之一中会发生什么?您将进入未定义的行为,并且您的应用程序可能会出现段错误(如果幸运的话)。
要解决此问题,您需要在尝试检索Block
对象之前比较所有向量的大小。
例如
Block b;
if ((pos.a < rawSheets.size()) &&
(pos.b < rawSheets[pos.a].countries.size()) &&
(pos.c < rawSheets[pos.a].countries[pos.b].cities.size()) &&
(pos.d < rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks.size()))
{
b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
}
你真的每次需要一个块时都这样做吗?!
你可以这样做,或者你至少可以把它包在一个类中......
例子:
class RawSheet
{
Block & FindBlock(const Pos &pos);
std::vector<Country> m_countries;
};
Block & RawSheet::FindBlock(const Pos &pos)
{
if ((pos.b < m_countries.size()) &&
(pos.c < m_countries[pos.b].cities.size()) &&
(pos.d < m_countries[pos.b].cities[pos.c].blocks.size()))
{
return m_countries[pos.b].cities[pos.c].blocks[pos.d];
}
else
{
throw <some exception type here>;
}
}
然后你可以像这样使用它:
try
{
Block &b = rawSheets[pos.a].FindBlock(pos);
// Do stuff with b.
}
catch (const <some exception type here>& ex)
{
std::cout << "Unable to find block in sheet " << pos.a << std::endl;
}
至少,您可以继续在RawSheet
类中使用向量,但由于它在方法中,您可以在以后删除向量滥用,而无需在其他地方更改任何代码(请参阅:得墨忒耳法则)!