程序员笔试(1)--数组和字符串

数组和字符串是最简单的数据结构,它们在一块连续的内存空间中分别存储数字和字符,因此将这两种简单的数据结构总结一下。

数组

数组必须在创建时指定大小,根据指定大小预先分配内存。所以数组的缺点就是大小固定不够灵活,而且空间利用率不高,就算你只需要存储一个数字,也需要为所有数据预先分配内存。
为了弥补这一缺点,C++ STL 提供了动态数组vector容器,vector可以根据存储的元素数量动态调整数组大小。例如:当vector容器内元素数量等于容器的容量(capacity),我们需要再向其中添加元素时,系统会为vector分配一片新的连续内存,来保证容器有内存空间存储新的元素。开辟新的内存空间的时间复杂度是O(n),为了避免每次添加一个元素都要开辟新的内存空间,我们可以每次分配新的内存大小为原数组大小的两倍,根据聚合分析可知,n个数组操作的期望时间复杂度为O(1)。

数组的优点则在于随机访问时间复杂度为O(1),由于数组存储在一片连续的内存当中,所以可以通过首个元素的内存地址+k倍的每个元素所占的内存来获得第k + 1 个元素的内存地址。根据这一特性,可以构造直接寻址的哈希表高效的解决一些问题。

数组和指针

数组和指针有非常密切的联系,当我们声明一个数组时,该数组名则是数组首个元素的地址。一般情况下我们都可以将数组名和指针当作一回事。但是在使用sizeof和decltype运算符时,数组和指针有很大的区别。可以看下面的代码(出自《剑指offer》2.3.1)。

int GetSize(int data[]){
    return sizeof(data);
    }
int _tmain(int argc,_TCHAR* argv[]){
    int data1[] = {1,2,3,4,5};
    int size1 = sizeof(data1);
    int *data2 = data1;
    int size2 = sizeof(data2);
    int size3 = GetSize(data1);
    printf(%d,%d,%d,size1,size2,size3);
}

代码最后输出是20,4,4。首先data1声明为数组,因此sizeof(data1)就是求数组的大小,5个int型变量总共占20字节的内存。而data2申明为指针,尽管它指向data1的第一个数组,但是它本质上还是指针,对于32位系统来说,所有指针变量的内存大小都为4字节(64位为8字节)。而size3为4的原因是,数组不能作为函数的参数,当传递数组作为函数参数时,数组会自动退化为指针。值得注意的是,由于数组不保存关于元素大小的数据,因此将数组作为参数传递时,在函数内部不能得到数组的大小,必须在函数外部显示的利用sizeof(a)/sizeof(a[0])来获取数组大小,通过参数再传递给函数。

字符串

C++中的都以’\0’结尾,这样能方便的找到字符串的尾部。因此每个字符串都会增加一个字符的开销,需要小心越界访问。比如:

char str[10];
strcpy (str,"0123456789");

由于我们声明的字符串只有10个字节的空间,而”0123456789”实际上有11个字符(包括尾子符’\0’),因此赋值出错,字符串应至少 有11个字节的内存空间。

为了节约内存,C++将常量字符串放在一个特定的内存空间(常量内存)中,当几个字符串指针都指向同一个字符串时,它们实际的指向地址是相同的。但是如果用常量字符串初始化字符串数组的话,情况却有所不同。因为初始化字符串数组时,字符串数组会重新开辟一片内存,然后将常量字符串的值拷贝到新的地址当中。因此,初始化两个不同的字符串数组时,即使数组内存储的字符串是相同的,两个字符串数组的内存地址也不同,因此数组名指针指向的地址也不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值