Eureka!

Keep thinking.

导航

无名形参:井底蛙的困惑

Posted on 2008-09-23 17:23  Kid.Loki  阅读(976)  评论(2编辑  收藏  举报

1. whoops... something weird

事情的起因是在《STL源码剖析》中看到了这样一个函数:

1 void splice(iterator position, list&, iterator i) {
2     iterator j = i;
3     ++j;
4     if (position == i || position == j) return;
5     transfer(position, i, j);
6 }

简洁、清晰,唯一令我困惑的是list&的作用:它显然没什么作用。

2. anonymous formal parameter

不管怎样,list&是一个无名形参,这一点不会错。那就想想什么样的情况下会用无名形参。

Type& operator++ ();
Type
& operator++ (int);

这是一种情况:为了触发重载。更一般地,如果函数的行为只取决于参数的类型,那么就可以书写无名形参以使代码干净整洁。不过即使回忆起这一点,splice的list&也还是很怪异,尤其是考虑到splice乃list类的成员函数,若说list&还有可能被换成vector&,那是没道理的。

考虑另一种可能。

1 double func(double x, double y, double (*fptr)(doubledouble)) {
2     return fptr(x, y);
3 }

这是有意设计的一个函数,其第三个参数是函数指针,典型的被指函数可能有求和、求差等等,但也可能需要这样的操作:求y的平方。为了能被fptr指向,某个平方函数就必须这样定义:

double ySquare(double x, double y) { return y * y; }
这个写法的瑕疵还是不整洁,以至于在高警告级别(例如vs2005的/W4)下会得到warning C4100:"x":未引用的形参。为了安抚编译器,ySquare需要写得更好些:

double ySquare(doubledouble y) { return y * y; }

函数指针一说虽然仍不能直接解释splice的list&,但已接近答案了。

3、at last...

函数指针实际上是规定了一套标准,所有的被指函数都应当符合这一标准,只不过ySquare认为x参数没什么用。

STL也是规定了一套标准,所有的STL实现版本都应当符合这一标准,只不过SGI的实现版本认为splice的list&参数没什么用。事情最终就是这么简单。

查阅了C++标准(ISO/IEC 14882:2003(E)),人家这么写:

void splice (iterator position, list<T, Allocator>& x, iterator i);

Effects: Inserts an element pointed to by i from list x before position and removes the element from x. The result is unchanged if position == i or position == ++i. Invalidates only the iterators and references to the spliced element.

Throws: Nothing.

Requires: i is a valid dereferenceable iterator of x.

Complexity: Constant time.

两下一对比可以得出结论:SGI的splice默认i所在的list为x,可算完美地遵循了标准。

4、conclusion

最基本的事实最容易忘记。

盯着极小的局部看问题,那样的困惑是井底之蛙的困惑。

5、new problem

splice中的list&为什么存在?因为是标准规定的。可其实我关心的是标准为什么要这么定。要满足这个好奇心就需要把各个实现版本的STL拿来比一比,到时候自然各有各的道理。

一个问题的解决总是带来更多的问题。有空再说吧。