- 注册时间
- 2005-4-8
- 最后登录
- 1970-1-1
|
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:- void f(int a[], int s)
- {
- // do something with a; the size of a is s
- for (int i = 0; i<s; ++i) a[i] = i;
- }
- int arr1[20];
- int arr2[10];
- void g()
- {
- f(arr1,20);
- f(arr2,20);
- }
复制代码 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:- void f(vector<int>& v)
- {
- // do something with v
- for (int i = 0; i<v.size(); ++i) v[i] = i;
- }
- vector<int> v1(20);
- vector<int> v2(10);
- void g()
- {
- f(v1);
- f(v2);
- }
复制代码 Since an array doesn't know its size, there can be no array assignment:- void f(int a[], int b[], int size)
- {
- a = b; // not array assignment
- memcpy(a,b,size); // a = b
- // ...
- }
复制代码 Again, I prefer vector:- void g(vector<int>& a, vector<int>& b, int size)
- {
- a = b;
- // ...
- }
复制代码 Another advantage of vector here is that memcpy() is not going to do the right thing for elements with copy constructors, such as strings.- void f(string a[], string b[], int size)
- {
- a = b; // not array assignment
- memcpy(a,b,size); // disaster
- // ...
- }
- void g(vector<string>& a, vector<string>& b, int size)
- {
- a = b;
- // ...
- }
复制代码 An array is of a fixed size determined at compile time:- const int S = 10;
- void f(int s)
- {
- int a1[s]; // error
- int a2[S]; // ok
- // if I want to extend a2, I'll have to change to an array
- // allocated on free store using malloc() and use realloc()
- // ...
- }
复制代码 To contrast:- const int S = 10;
- void g(int s)
- {
- vector<int> v1(s); // ok
- vector<int> v2(S); // ok
- v2.resize(v2.size()*2);
- // ...
- }
复制代码 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:- class Base { void fct(); /* ... */ };
- class Derived { /* ... */ };
- void f(Base* p, int sz)
- {
- for (int i=0; i<sz; ++i) p[i].fct();
- }
- Base ab[20];
- Derived ad[20];
- void g()
- {
- f(ab,20);
- f(ad,20); // disaster!
- }
复制代码 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:- void f(vector<Base>& v)
- {
- for (int i=0; i<v.size(); ++i) v[i].fct();
- }
- vector<Base> ab(20);
- vector<Derived> ad(20);
- void g()
- {
- f(ab);
- f(ad); // error: cannot convert a vector<Derived> to a vector<Base>
- }
复制代码 I find that an astonishing number of novice programming errors in C and C++ relate to (mis)uses of arrays. |
|