1

STL 容器的一个常见模式是:

map<Key, Value> map;
for(map<Key, Value>::iterator iter = map.begin(); iter != map.end(); ++iter)
{
  ...
}

因此,为了避免编写模板参数的声明,我们可以在某处这样做:

typedef map<Key, Value> TNiceNameForAMap;

但是,如果此映射仅用于单个函数或单个迭代,则这是一个令人讨厌的开销。

这个typedef有什么办法吗?

4

7 回答 7

10

不确定您所说的“开销”是什么意思。如果它简化了您编写代码的方式,请使用它,否则请坚持使用速记。

如果它仅在受限范围内使用,请将 typedef 放在同一范围内。然后它就不需要发布、记录或出现在任何 UML 图上。例如(我并不认为这是在其他方面最好的代码):

int totalSize() {
    typedef std::map<Key, Value> DeDuplicator;
    DeDuplicator everything;

    // Run around the universe finding everything. If we encounter a key
    // more than once it's only added once.

    // now compute the total
    int total = 0;
    for(DeDuplicator::iterator i = everything.begin(); i <= everything.end(); ++i) {
        total += i->second.size(); // yeah, yeah, overflow. Whatever.
    }
    return total;
}

结合 Ferruccio 的建议(如果您正在使用 boost),循环变为:

BOOST_FOREACH(DeDuplicator::pair p, everything) {
    total += p.second.size();
}

并结合 bk1e 的建议(如果您使用 C++0x 或具有其中的功能),并假设 BOOST_FOREACH 以我认为应该基于它通常可以处理兼容类型的隐式转换的方式与 auto 交互:

std::map<Key, Value> everything;
// snipped code to run around...
int total = 0;
BOOST_FOREACH(auto p, everything) {
    total += p.second.size();
}

不错。

于 2008-09-24T03:07:19.057 回答
5

您可以使用Boost.Foreach

于 2008-09-24T03:13:41.837 回答
3

C++ 标准的未来版本(称为C++0x)将引入关键字的新用途auto,允许您编写如下内容:

map<Key, Value> map;
for(auto iter = map.begin(); iter != map.end(); ++iter)
{
  ...
}
于 2008-09-24T03:39:50.713 回答
2

我个人认为MYMAP::iteratormap<int,string>::iterator甚至std::map<int, std::string>::iterator更具可读性,所以我总是使用 typedef。唯一的开销是一行代码。

编译代码后,可执行文件的大小或速度将没有差异。这只是关于可读性。

于 2008-09-24T03:14:05.360 回答
0

如果 typedef 对于单个函数来说是本地的,它甚至不需要是一个好听的名字。使用 X 或 MAP,就像在模板中一样。

于 2008-09-24T03:58:22.383 回答
0

C++0x 还将提供基于范围的 for 循环,这类似于其他语言中的迭代 for 循环。

不幸的是,GCC 还没有实现基于范围的 for(但确实实现了 auto)。

编辑:同时,还考虑对迭代器进行类型定义。它不能绕过一次性使用的 typedef(除非你把它放在头文件中,这始终是一个选项),但它使生成的代码缩短了一个 ::iterator。

于 2008-09-24T04:59:58.943 回答
0

在过去的几年里,我真的试图摆脱使用手动编写的循环而不是使用 STL 算法。您上面的代码可以更改为:

struct DoLoopBody {
  template <typename ValueType>
  inline void operator()(ValueType v) const {
    // ...
  }
};

std::for_each (map.begin(), map.end(), DoLoopBody ());

不幸的是,DoLoopBody 类不能是本地类,这通常被强调为一个缺点。但是,我认为这是一个优势,因为现在可以单独对循环体进行单元测试。

于 2008-09-24T07:54:10.023 回答