C++sizeof使用规则及陷阱分析二
来源:优易学  2011-11-6 10:30:15   【优易学:中国教育考试门户网】   资料下载   IT书店

  (6)、向函数传递数组的问题。

  考虑下面的问题:

  1 #include <iostream>

  2 using namespace std;

  3

  4 int Sum(int i[])

  5 {

  6 int sumofi = 0;

  7  for (int j = 0; j < sizeof(i)/sizeof(int); j++) //实际上,sizeof(i) = 4

  8 {

  9 sumofi += i[j];

  10 }

  11 return sumofi;

  12 }

  13

  14 int main()

  15 {

  16  int allAges[6] = {21, 22, 22, 19, 34, 12};

  17 cout<<Sum(allAges)<<endl;

  18 system("pause");

  19 return 0;

  20 }

  Sum的本意是用sizeof得到数组的大小,然后求和。但是实际上,传入自函数Sum的,只是一个int 类型的指针,所以sizeof(i)=4,而不是24,所以会产生错误的结果。解决这个问题的方法使是用指针或者引用。

  使用指针的情况:

  1 int Sum(int (*i)[6])

  2 {

  3 int sumofi = 0;

  4 for (int j = 0; j < sizeof(*i)/sizeof(int); j++) //sizeof(*i) = 24

  5 {

  6 sumofi += (*i)[j];

  7 }

  8 return sumofi;

  9 }

  10

  11 int main()

  12 {

  13  int allAges[] = {21, 22, 22, 19, 34, 12};

  14 cout<<Sum(&allAges)<<endl;

  15 system("pause");

  16 return 0;

  17 }

  在这个Sum里,i是一个指向i[6]类型的指针,注意,这里不能用int Sum(int (*i)[])声明函数,而是必须指明要传入的数组的大小,不然sizeof(*i)无法计算。但是在这种情况下,再通过sizeof来计算数组大小已经没有意义了,因为此时大小是指定为6的。

  使用引用的情况和指针相似:

  1 int Sum(int (&i)[6])

  2 {

  3 int sumofi = 0;

  4 for (int j = 0; j < sizeof(i)/sizeof(int); j++)

  5 {

  6 sumofi += i[j];

  7 }

  8 return sumofi;

  9 }

  10

  11 int main()

  12 {

  13  int allAges[] = {21, 22, 22, 19, 34, 12};

  14 cout<<Sum(allAges)<<endl;

  15 system("pause");

  16 return 0;

  17 }

  18

  这种情况下sizeof的计算同样无意义,所以用数组做参数,而且需要遍历的时候,函数应该有一个参数来说明数组的大小,而数组的大小在数组定义的作用域内通过sizeof求值。因此上面的函数正确形式应该是:

  1 #include <iostream>

  2 using namespace std;

  3

  4 int Sum(int *i, unsigned int n)

  5 {

  6 int sumofi = 0;

  7 for (int j = 0; j < n; j++)

  8 {

  9 sumofi += i[j];

  10 }

  11 return sumofi;

  12 }

  13

  14 int main()

  15 {

  16  int allAges[] = {21, 22, 22, 19, 34, 12};

  17  cout<<Sum(i, sizeof(allAges)/sizeof(int))<<endl;

  18 system("pause");

  19 return 0;

  20 }

  (7)、C风格字符串与C++风格字符串类(String)的sizeof和strlen

  考虑下面的问题:

  1 #include <string>

  2 using namespace std;

  3

  4 char a[] = "abcdef";

  5 char b[20] = "abcdef";

  6 string s = "abcdef";

  7

  8  cout<<strlen(a)<<endl;  // 6,字符串长度9  cout<<sizeof(a)<<endl;  // 7,字符串容量10  cout<<strlen(b)<<endl;  // 6,字符串长度11  cout<<sizeof(b)<<endl;  // 20,字符串容量12  //cout<<strlen(s)<<endl;  // 错误!s不是一个字符指针。

  13  cout<<sizeof(s)<<endl;  // 16, 这里不代表字符串的长度,而是string类的大小

  14

  15 a[1] = '\0';

  16 cout<<strlen(a)<<endl; // 1

  17  cout<<sizeof(a)<<endl;  // 7,sizeof是恒定的,因为是前面已经固定分配过7个单元,虽然现在字符串变为空串

  18

  记住:String是class类型。(关于class类型的sizeof请参见第五节)

  strlen是寻找从指定地址开始,到出现的第一个0之间的字符个数,他是在运行阶段执行的,而sizeof是得到数据的大小,在这里是得到字符串的容量。所以对同一个对象而言,sizeof的值是恒定的。string是C++类型的字符串,他是一个类,所以sizeof(s)表示的并不是字符串的长度,而是类string的大小。strlen(s)根本就是错误的,因为strlen的参数是一个字符指针,如果想用strlen得到s字符串的长度,应该使用sizeof(s.c_str()),因为string的成员函数c_str()返回的是字符串的首地址。实际上,string类提供了自己的成员函数来得到字符串的容量和长度,分别是Capacity()和Length()。string封装了常用了字符串操作,所以在C++开发过程中,最好使用string代替C类型的字符串。

  STL中的String类:

  string的sizeof和平台相关的,string类最简单的可以近似认为是包含两个数据成员:char *指针成员( 表示字符数组)和 int成员(表示字符串长度)。但是事实上并不是这样定义的,可能还有其他数据成员,如编译器插入指针vptr等。因此根据不同的实现,可以查看String类的定义中如何定义。比如在我现在机器上,sizeof(string) = 16.

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训