给我一个不做C++程序员的理由
来源:互联网 发布:筑业标书软件 编辑:程序博客网 时间:2024/04/28 20:29
我是一个C++菜鸟,一直在努力成长,希望有一天会成为C++大虾。谁知道总是受到打击。今天看到一篇老外写的文章,又被当头一棒。
一个简单的问题,给你一个数组,例如a[10],如何得到它的元素个数?
第一反应是,很简单啊,#define countof(array) (sizeof(array)/sizeof(array[0]) )
但是它的问题是,如果array是一个指针,而不是数组,那么coutof(array)的值就是1了(假定array是int*)
而且,array还有可能是一个自定义类的对象,比如下面这个类的对象,那么结果就是这个对象的大小除以p[0]的大小了(array[0]定义成返回p[0])。
class IntArray
{
private:
int * p;
size_t size;
public:
int & operator [] ( size_t i );
} x;
因此我们需要更进一步的深入,看看下面这个实现
template <typename T, size_t N>
size_t countof( T array[N] )
{
return N;
}
它可以了吗?不行!为什么?因为参数里面的N根本没有用,T array[N]被编译器视作T array*,N被直接无视了。因此这个函数根本不可能返回N。
那怎么办呢?我们接着改造吧:
template <typename T, size_t N>
size_t countof( T (&array)[N] )
{
return N;
}
这下我们用引用代替指针做参数,编译器就知道这里一定要传一个数组进来了,指针的不要,而且数组的大小是N。因此成功返回N。
这就是我们想要的。
OK了?依然不完美!为什么?
因为这是个函数,不是宏!函数肿么了?看看下面这个例子就知道了:
int x[10];
int y[ 2*countof(x) ]; // twice as big as x
这个显然编译不能通过。因为编译器不能在编译的时候就知道数组y的大小,它没法在编译时确定函数返回值啊。
肿么办?办法就是要在编译的时候就确定返回值,进而得到N!
?还能这样?Mission Impossible?
一个聪明的人想出了下面的办法:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N]; //函数,能在编译时确定返回值的
#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))//我们想要的宏
@#@$@%@%@%@%$%&(*^)&^)^) ==!!!!!!!
[BTW:]我横竖看了这几行代码半天,木有看懂神马意思。大虾们原谅我这个菜鸟吧!
看了老外的解释,我终于明白了:
char ( &_ArraySizeHelper( ... ))[N];
省略部分内容以便于理解。现在很明显了,_ArraySizeHelper是一个函数,这个函数的返回值是“((一个大小为N的)字符数组的)引用”
真够拗口的。我把所有定于都用圆括号括起来,方便理解。
上面说了,编译器可以在编译的时候就可以知道这个函数的返回值。怎么回事呢?
看看下一行代码,
我们把 _ArraySizeHelper( array ) 单独挖出来,把它暂时替换成X
#define countof( array ) (sizeof(X))
X是_ArraySizeHelper的返回值,实际上并不需要真正调用这个函数就可以确定它的返回值X!
还记得吗?它的返回值是“((一个大小为N的)字符数组的)引用”
于是,sizeof(X) = sizeof(“((一个大小为N的)字符数组的)引用”) = N!
因此,
#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))
的结果就是N。
因为它是一个宏,因此
int x[10];
int y[ 2*countof(x) ]; // twice as big as x
可以编译通过。
OK了吗?别紧张。这个实现已经在stdlib.h里面用到了,所以可以认为OK了。
终于可以松口气了!下面是stdlib.h里面的实现:
template <typename _CountofType, size_t _SizeOfArray>
char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];
#define _countof(_Array) sizeof(*__countof_helper(_Array))
和上面那个实现的唯一差别就是把引用换成了指针。这个函数返回值是“指向一个((大小为N的)字符数组的)指针”。
到了这里,我已经心生怨念了。看似这么简单的一个功能,为什么搞得这么复杂?
好消息是,我们可以无视这些复杂的实现,直接用_coutof 这个库里面提供的函数。但是C++和其它语言不一样的地方是,作为一个C++程序员,你有时候需要知道库函数是怎么样实现的,才能写出更好的程序。如果你不知道上面那些,你怎么知道有_coutof呢?
会不会直接在代码中用“sizeof(array)/sizeof(array[0])"呢?PHP程序员肯定不会这样做。
这是不是一个不做C++程序员的理由呢?
- 给我一个不做C++程序员的理由
- 给我一个活下去的理由
- 给我一个去北京的理由
- 每天给我一个幸福的理由
- 给我一个不坚强的理由
- 给我一个理由忘记 那么爱我的你
- 给我十个选择程序员做男朋友的理由
- 不做护士的理由
- 给我一个喜欢你的理由-品牌定位
- 给我一个理由阿哥阿姐
- 我的单曲《给我一个不爱的理由EP》发行了
- 给我加工资的几个理由
- 谢谢你,给了我忘记的理由
- 给我你让离开的理由
- 给我一个理由,让我买了你
- 转载:给自己一个成功的理由
- 给自己一个成功的理由
- 给自己一个拼搏的理由
- sql convert()函数的用法
- 校园博客系统需求分析
- S3C2440启动代码中应用程序执行环境的初始化
- ubuntu 11.04 安装jdk6
- 单片机数码管段码
- 给我一个不做C++程序员的理由
- 虚拟机上Linux获取主机win7上文件的简单方法
- 摩托me525 root并精简系统后出现问题
- 基于linux2.6.38.8内核zImage文件的自解压详解
- vc学习(四)鼠标移动椭圆
- Web应用程序框架(Web Application Framework)
- dll加载卸载工具(开源)
- 排序算法
- NYOJ 325 zb的生日 【dp问题】