设为首页 加入收藏

TOP

14.2.2 阻止退化
2013-10-07 15:06:32 来源: 作者: 【 】 浏览:63
Tags:14.2.2 阻止 退化

14.2.2  阻止退化

我认为这种从数组到指针的退化还不能算是一个缺陷,如果没有它,某些地方的代码的简洁性可能就会大打折扣,并且还可能损失许多灵活性。话虽如此,有时这个特性确实会带来麻烦,本章以及第27章和第33章我们都会注意到这一点。

对于内建的数组来说,没有任何手段能够阻止从数组到指针的赋值动作。当数组作为函数参数时,人们可以把函数的参数声明为数组的指针或引用,后者虽然不是指针,但是仍然没有办法阻止函数内部的代码将它转换为一个指针。

你或许想知道为什么我们要关心这些。数组能够退化成指针这一特性导致了像p = ar这样的代码的广泛出现,它们的基础就是该特性。而相比之下,一个更为精确的形式p = &ar[0]反倒没那么常见。显然,前者更为方便,但从泛型编程(www.cppentry.com)的角度来说,它却会带来负面影响。考虑这样的情况:你定义了一个类类型,该类的行为在某些方面类似于数组,对此你得为它提供一个下标索引操作符,像这样:

  1. class IntArray  
  2. {  
  3.   . . .  
  4.   int const &operator [](size_t offset) const;  
  5.   int       &operator [](size_t offset);  
  6.   . . .  

通常,这种方式跟提供隐式的转换操作符相比要更优越一些(我们将在第32和33章详细讨论)。尽管该类现在支持像数组那样的下标索引语法,但是它并不提供向指针的隐式转换。因此,如果你希望在"那些利用了数组至指针的退化能力"的代码中使用该类型的话,你就会碰壁。

序列式容器提供的随机访问迭代器[Aust1999, Muss2001]也存在类似的问题。由于将迭代器实现为类是合法的,所以如果你的代码依赖于数组退化的话,你就遇到麻烦了。例如,pod_vector容器(见32.2.8小节)通过memmove()实现插入操作,像这样:

  1. memmove(&first[0], &last[0], . . . 

然而,要是你像我当初那样想当然地认为迭代器是指针而并非行为像指针(仅在STL迭代器概念[Aust1999, Muss2001]所描述的那些方面)的类型的话,你就有可能写出这样的代码:
  1. memmove(first, last, . . . // 迭代器不能转换为void* 

这对于那些通过类来定义迭代器类型的标准库实现是不能通过编译的。因此,克制自己使用数组退化特性是值得的。即使你的代码并不会因此陷入纠缠不清的错误,这么做也至少能够提醒你自己在语法背后发生了什么。
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇14.1 不要重复你自己 下一篇14.3 dimensionof()

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: