易码技术论坛

 找回密码
 加入易码
搜索
查看: 711547|回复: 4

[教程] What's wrong with arrays?

[复制链接]
发表于 2007-10-7 20:10:07 | 显示全部楼层 |阅读模式
http://www.research.att.com/~bs/bs_faq2.html#arrays

In terms of time and space, an array is just about the optimal construct for accessing a sequence of objects in memory. It is, however, also a very low level data structure with a vast potential for misuse and errors and in essentially all cases there are better alternatives. By "better" I mean easier to write, easier to read, less error prone, and as fast.

The two fundamental problems with arrays are that

an array doesn't know its own size
the name of an array converts to a pointer to its first element at the slightest provocation
Consider some examples:
  1.         void f(int a[], int s)
  2.         {
  3.                 // do something with a; the size of a is s
  4.                 for (int i = 0; i<s; ++i) a[i] = i;
  5.         }

  6.         int arr1[20];
  7.         int arr2[10];

  8.         void g()
  9.         {
  10.                 f(arr1,20);
  11.                 f(arr2,20);
  12.         }
复制代码
The second call will scribble all over memory that doesn't belong to arr2. Naturally, a programmer usually get the size right, but it's extra work and ever so often someone makes the mistake. I prefer the simpler and cleaner version using the standard library vector:
  1.         void f(vector<int>& v)
  2.         {
  3.                 // do something with v
  4.                 for (int i = 0; i<v.size(); ++i) v[i] = i;
  5.         }

  6.         vector<int> v1(20);
  7.         vector<int> v2(10);

  8.         void g()
  9.         {
  10.                 f(v1);
  11.                 f(v2);
  12.         }
复制代码
Since an array doesn't know its size, there can be no array assignment:
  1.         void f(int a[], int b[], int size)
  2.         {
  3.                 a = b;        // not array assignment
  4.                 memcpy(a,b,size);        // a = b
  5.                 // ...
  6.         }
复制代码
Again, I prefer vector:
  1.         void g(vector<int>& a, vector<int>& b, int size)
  2.         {
  3.                 a = b;       
  4.                 // ...
  5.         }
复制代码
Another advantage of vector here is that memcpy() is not going to do the right thing for elements with copy constructors, such as strings.
  1.         void f(string a[], string b[], int size)
  2.         {
  3.                 a = b;        // not array assignment
  4.                 memcpy(a,b,size);        // disaster
  5.                 // ...
  6.         }

  7.         void g(vector<string>& a, vector<string>& b, int size)
  8.         {
  9.                 a = b;       
  10.                 // ...
  11.         }
复制代码
An array is of a fixed size determined at compile time:
  1.         const int S = 10;

  2.         void f(int s)
  3.         {
  4.                 int a1[s];        // error
  5.                 int a2[S];        // ok

  6.                 // if I want to extend a2, I'll have to change to an array
  7.                 // allocated on free store using malloc() and use realloc()
  8.                 // ...
  9.         }
复制代码
To contrast:
  1.         const int S = 10;

  2.         void g(int s)
  3.         {
  4.                 vector<int> v1(s);        // ok
  5.                 vector<int> v2(S);        // ok
  6.                 v2.resize(v2.size()*2);
  7.                 // ...
  8.         }
复制代码
C99 allows variable array bounds for local arrays, but those VLAs have their own problems.
The way that array names "decay" into pointers is fundamental to their use in C and C++. However, array decay interact very badly with inheritance. Consider:
  1.         class Base { void fct(); /* ... */ };
  2.         class Derived { /* ... */ };

  3.         void f(Base* p, int sz)
  4.         {
  5.                 for (int i=0; i<sz; ++i) p[i].fct();
  6.         }

  7.         Base ab[20];
  8.         Derived ad[20];

  9.         void g()
  10.         {
  11.                 f(ab,20);
  12.                 f(ad,20);        // disaster!
  13.         }
复制代码
In the last call, the Derived[] is treated as a Base[] and the subscripting no longer works correctly when sizeof(Derived)!=sizeof(Base) -- as will be the case in most cases of interest. If we used vectors instead, the error would be caught at compile time:
  1. void f(vector<Base>& v)
  2.         {
  3.                 for (int i=0; i<v.size(); ++i) v[i].fct();
  4.         }

  5.         vector<Base> ab(20);
  6.         vector<Derived> ad(20);

  7.         void g()
  8.         {
  9.                 f(ab);
  10.                 f(ad);        // error: cannot convert a vector<Derived> to a vector<Base>
  11.         }
复制代码
I find that an astonishing number of novice programming errors in C and C++ relate to (mis)uses of arrays.
发表于 2007-10-7 22:23:57 | 显示全部楼层
array被完全当作base pointer + index * offset width来操作,vector加入一些"类智能"侦错功能(由OO特性提供)。大概是这个意思吧。
发表于 2007-10-12 16:04:50 | 显示全部楼层
LZ,E文不好时能否给个中文版啊?
发表于 2007-10-13 15:03:16 | 显示全部楼层
用金山快译
 楼主| 发表于 2007-10-13 23:57:18 | 显示全部楼层

回复 3# 的帖子

大部分时候,你都不可能找到一个英文版呢
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-3-29 05:42 , Processed in 0.009503 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表