c++:在STL容器中何时使用范围检查

ZDNet软件频道 时间:2004-06-02 作者:Builder.com |  我要评论()
本文关键词:cpptips
访问内建数组的元素是一种速度非常快的操作,因为 C++ 在运行时期不执行范围检查。但是,这样做的后果是,一个不小心的语句会把程序带入一个未定义的状态。
本文译自Builder.com,未经许可请勿转载

访问内建数组的元素是一种速度非常快的操作,因为 C++ 在运行时期不执行范围检查。但是,这样做的后果是,一个不小心的语句会把程序带入一个未定义的状态,例如:

char s[10];
void func(char * str)
{
 s[12]=''; //undefined; writing past a buffer's end
}

一些程序员错误地认为 STL 容器,比如 std::vector 和 std::string 等,除了其它优点之外还实现了自动的范围检查。事实上,情况并非如此。在使用重载的 [] 操作符访问一个 vector 的元素时,事实上并没有执行范围检查。同样对其它序列容器,情况也是如此,这样的容器有 std::string 和 std::dequeue 等。

范围检查会带来可观的空间开销和运行时间开销。强加这种开销给用户将会使得这些容器显著地变慢,因此变得用处不大。相反,C++ 坚持“相信程序员”的风格。注意,范围检查在很多情况下是没有必要的。

std::vector<int> vi;
//..fill the vector
for (int n=0; n<vi.size(); n++)
{
 std::cout<<vi[n]<<std::endl; //n is always valid
}

重载的 [] 操作符是一个成熟的功能。其实现的效率非常高,并且其调用通常是内联的(inline)。这样,它几乎提供了与其它相应内建操作相同的速度。

什么时候范围检查是不同避免的

只有很少的情况下范围检查才是不可避免的。在这些情况下,STL 容器提供一个更加安全(但是速度也更慢)的方法来访问元素,即 at() 成员函数。at() 在功能上与重载的 [] 操作符很相似,但是它执行范围检查。如果参数是无效的,at() 就抛出一个 std::out_of_range 异常。因此,我们应该总是将 at() 调用包围在一个 try 代码块中,并提供一个与之匹配的 catch() 子句:

void assign(std::string & s, int index, char val)
{
 try
 {
  s.at(index)=val;
 }
 catch (std::out_of_range & exc)
 {
  std::cerr <<exc.what();
 }
}

总之,使用 [] 操作符访问容器元素的效率是很高的,如果范围检查不可避免,那么可以使用 at() 替代操作符 []。记住,在这种情况下一定要把对 at() 函数的调用包围在一个 try 代码块中并提供一个匹配的 catch() 子句。


本文作者:Danny Kalev 是一位系统分析员、软件工程师,他具有14年在 C++ 和面向对象设计方面的经验。


责任编辑:李宁

欢迎评论投稿

百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134