简洁既是美,程序员应尽量尝试编写简洁的表达式,争取用简单的代码来实现更多的功能,当然,这也要看情况了(有时候也得考虑程序运行的时间嘛)。
在阅读C++Prime Plus到while语句时有一个讲一个数组内容复制到另一个数组的例子:
//arr1 is an array if ints
int *source=arr1;
size_t sz=sizeof(arr1)/sizeof(*arr1); //number of elements
int *dest=new int[sz];
while(source!=arr1+sz)
*dest++=*source++; //copy element and increment pointers
首先初始化source和dest,并使他们各自指向所关联的数组的第一个元素。while循环条件判断是否已经到达要复制的数组的末尾。如果没有,继续执行循环。循环体只有单个语句,实现元素的复制,并对两个指针做自增操作,使他们指向对应数组的下一个元素。
此处,循环体中的语句:
*dest++=*source++;
即所说的简约。这个表达式也等价于:
{
*dest=*source;
++dest;
++source;
}
根据上述,我在编译器上编写了下面的程序:
#include<iostream>
using namespace std;
int main(){
char arr1[]="string";
char* source=arr1;
size_t sz=sizeof(arr1)/sizeof(*arr1);
char *dest=new char[sz];
while(source!=arr1+sz)
*dest++=*source++;
cout<<arr1<<endl;
cout<<dest<<endl;
cout<<"**********"<<endl;
cout<<sz<<endl;
delete []dest;
return 0;
}
程序的作用为将数组arr1复制到dest中,并输出arr1和dest。但运行的结果并不是我想的:
问题
首先,我想到的是是不是数组arr1中的内容并没有复制到dest中,所以我对程序进行了但步跟踪,最后找到了原因:
开始,我们定义了一个arr1数组,接着使用new表达式动态创建了一个数组,并返回了指向新创建对象的指针dest,接着利用source指针和
dest指针复制了元素,这看起来并没有错。但是我忽略了一点,dest是一个指向动态数组的指针而不是数组名,可是我在最后的输出时把dest指针当做
了数组名(cout<<dest<<endl;)。
让我们来看看C++ Prime Plus上是怎么描述new表达式的:new表达式动态创建对象时,只需指定其数据类型,而不必为该对象命名,取而代之的是,new表达式返回指向新创建对象的指针,我们通过该指针来访问此对象。
虽然我最后输出时的确是使用dest指针来访问我们创建的动态数组,但需要知道的是此时的dest指针指的已经不是动态数组了。
如图,在程序执行while循环之前,source和dest指针分别指向arr1和动态数组的第一个元素,但执行了while循环后两个指针如图所示,所以此时再利用dest指针来访问动态数组是不行了。
解决方法:就像书上说的,对于new表达式动态创建的对象,我们通过返回的指针来访问此对象,而在本例中dest指针充当了工作指针,从而使得dest指针最后并没有指向动态数组,这样给我们访问动态数组不方便,所以我们可以再创建一个指针来代替dest指针充当工作指针。
程序更给如下:
//…
char *dest=new char[sz];
char *dest_p=dest;
while(source!=arr1+sz)
*dest_p++=*source++;
//….
程序运行结果如下:
总结:
1、简洁既是美,作为一个程序员应尽量做到自己编写的程序短小精悍,以比较少的代码使用更大的功能,有经验的程序员非常重视简练。要不断研究类似*dest++=*source++;的代码,最后达到一目了然的地步。
2、C++中,在使用new表达式创建动态对象时,我们会利用返回的指针来访问此对象,所以应该创建一个新的指针来充当工作指针,避免原指针最后知道我们不清楚的地方而对访问此对象造成麻烦。