C++语言基础知识学习:数组
小标 2018-07-10 来源 : 阅读 709 评论 0

摘要:本文主要向大家介绍了C++语言基础知识学习:数组,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

本文主要向大家介绍了C++语言基础知识学习:数组,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

一、数组

1. 定义数组

数组是由类型名,标识符和维数组成的复合数据类型。其中,类型名可以是内置类型或类类型,除引用之外,数组元素的类型还可以是任意的复合类型。

数组的维数必须用大于等于1的常量表达式定义。在定义数组时,可为其元素提供一组用逗号分隔的初值,这些初值用花括号{}括起来,称为初始化列表:

const unsigned array_size = 3;int ia[array_size] = {0, 1, 2};

如果没有显式提供元素初值,则数组元素会像普通变量一样初始化。

对于数组元素的显式初始化应当注意两点:

第一,显式初始化的数组不需指定数组维数值,例如

int ia[] = {2, 22, 222};

第二,如果指定维数大于列出的元素初值数,对剩余元素来说,内置类型初始化为零,类类型调用默认构造函数初始化。例如

double coords[3] = {}; // all elements default initialized to 0int nums[5] = {0, 1, 2}; // nums[3] and nums[4] default initialized to 0// lables[1] and labels[2] default initialized to empty stringstring labels[3] = {"Hello"};

总结来看,内置类型的数组,在定义后要进行初始化,对于显式初始化方式,一旦指定了其维数可确保所有元素都会被初始化,即使初始化列表中指定的元素初值数不足。而对于类类型的数组来说,在定义时就会调用默认构造函数初始化,如果显式初始化,则调用相应构造函数进行初始化。例如下面自己写的一个简单类数组:

#include using namespace std;

class Apple

{

    public:

    Apple(int startVer):m_version(startVer)

    {

    }

    int GetVersion()

    {

        return m_version;

    }

    

    private:

    int m_version;

};

int main(void){

    Apple iphones[4] = {4, 5, 6, 7};

    int latest = sizeof(iphones)/sizeof(iphones[0])-1;

    cout<<"iphone "<<iphones[latest].GetVersion()<<endl;

 

    return 0;

}

不管是内置类型数组(包括字符数组),还是类类型数组,都不支持直接复制与赋值操作。

一般通过下标操作符来访问数组的元素。在用下标访问元素时,vector使用vector::size_type作为下标的类型,而数组下标的正确类型是size_t。程序员必须对数组下标的使用负责,防止缓冲区溢出(buffer overflow)错误。

2. 数组下标与指针

在表达式中使用数组名时,该名字会自动转换为指向数组第一个元素的指针。使用指针的算术操作(pointer arithmetic)来获取指定内容的存储地址相比下标操作更加方便。例如:

int ia[] = {0, 2, 4, 6, 8};int last = *(ia +4); // ok: last initialized to value of ia[4]int *ip = ia; // ip points to ia[0]int *ip2 = ip+4; // ok: ip2 points to ia[4]

使用下标访问数组时,实际上是对指向数组元素的指针做下标操作。只要指针指向数组元素,就可以对它进行下标操作:

int *p = &ia[2];int j = p[1]; // ok: p[1] equivalent to *(p+1)int j = p[-2]; //ok: p[-2] equivalent to *(p-2), same to ia[0]

二、动态数组

数组类型的变量有三个重要的限制:

· 数组长度固定不变

· 在编译时必须知道其长度

· 数组只在定义它的块语句内存在

动态分配的数组不必在编译时知道其长度,通常在运行时才确定其数组长度,与数组变量不同,动态分配的数组将一直存在,直到程序显式释放它为止。

每一个程序在执行时都占用一块内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区(free store)或堆(heap)。C语言使用一对标准库函数malloc和free在自由存储区分配存储空间,而C++语言则使用new和delete表达式实现相同的功能。

1. 动态数组的定义与初始化

动态分配数组只需指定类型和数组长度,不必为数组对象命名,new表达式返回指向新分配数组的第一个元素的指针:

int *pia = new int[10]; // array of 10 uninitialized ints

inr *pia2 = new int[10](); // 10 elements of ints array initialized to 0

new表达式需要指定指针类型以及在方括号中给出的数组维数,该维数可以是任意的复杂表达式。在动态分配数组时,若想初始化内置类型,则只能采用值初始化方式,而类类型不管有没有值初始化都会调用默认构造函数初始化。总的来说,动态分配的数组,其数组元素只能初始化为元素类型的默认值,而不能采用初始化列表的方式提供初值。

2. 允许动态分配空数组

size_t n = get_size();int *p = new int[n];for(int *q = p; q != p + n; ++q)

    /* process the array *

上例中,即使n = 0(get_size返回0)时,程序仍能正常运行。C++虽然不允许定义长度为0的数组变量,但使用new动态创建长度为0的数组是合法的。

对数组为零的动态数组允许的操作包括:比较运算,指针加减零运算。

3. 动态空间的释放

如果不再需要使用动态创建的数组,程序员必须显式地将其占用的存储空间返还给自由存储区。C++中释放指针所指向的数组空间:

delete [] pia;

关键字delete与指针间的空方括号是必不可少的,否则将产生内存泄漏(memory leak)。

三、字符数组与C风格字符串

1. 字符数组

字符数组既可以用一组由花括号括起来,逗号隔开的字符字面值进行初始化,也可以用一个字符串字面值进行初始化。需注意的是字符串字面值包含一个额外的空字符(null)用于结束字符串,例如:

char chs1[] = {‘C’, '+', '+'};char chs2[] = {'C', '+', '+', '\0'};char chs3[] = "C++"; // null terminator added automatically

其中,字符数组chs2和chs3值相同,并且维数都是4。

动态字符数组的定义与初始化:

char *pNewChars = new char[newSize]; // uninitializedif(pNewChars != NULL)

{

    char *iter = pNewChars;

    while(iter != (pNewChars + newSize))

        *iter++ = '\0';

}

2. C风格字符串(C-style character string)

实际上,C风格字符串既不能确切地归结为C语言的类型,也不能归结为C++语言的类型,可以说它是以空字符null结束的字符数组,例如上面的ch2和ch3,字符串字面值是该类型的实例。

C++语言中一般通过(const) char*类型的指针来操纵C风格字符串。需要注意的是,C风格字符串一定是以null结束的,如果发现char*的数组中不是以null结束,那么它就不是C风格字符串,这样来看,C风格字符串其实是字符数组的一个子集。

const char* cp = "some value"; // null terminated

标准库类string

string类型支持长度可变的字符串。要使用string类对象,必须包含相关头文件:

#include


表1 几种初始化string对象的方式

   



string s1;                                  默认构造函数,空字符串

string s2(s1);                            将s2初始化为s1的一个副本

string s3("Value");                    将s3初始化为一个字符串字面值副本

string s4(n, 'c');                        将s4初始化为字符'c'的n个副本

   


表中的第三种初始化方式就是使用字符串字面值(属于C风格字符串类型)进行初始化string类对象的,但需要注意的是string类型不符合C风格字符串的特征,例如:

string str("Hi, C++");cout<<"string size = "<<str.size()<<endl; // size = 7

string对象会自动将字符串字面值末尾null结束符去掉,因此得到的string对象size = 7。但string类提供了一个名为c_str的成员函数来转换得到C风格字符串:

const char *cStr = str.c_str(); //ok

注意:c_str函数返回的指针是指向const char类型的数组,需要赋给const char*类型

C风格字符串的标准库函数

C语言标准库提供了一系列处理C风格字符串的库函数,需要包含C头文件:

#include

cstring是string.h头文件的C++版本,string.h文件则是C语言的标准库。


表2 C风格字符串的标准库函数

   



strlen(s)                               返回s的长度,不包括字符串结束符null

strcmp(s1, s2)                    比较两个字符串s1和s2是否相同,相等返回0;若s1大于s2返回正数,若s1小于s2返回负数

strcat(s1, s2)                    将字符串s2连接到s1,并返回s1

strcpy(s1, s2)                    将s2复制给s1,并返回s1

strncat(s1, s2, n)           将s2的前n个字符连接到s1后面,并返回s1

strncpy(s1, s2, n)           将s2的前n个字符复制给s1,并返回s1

   


在使用这些标准库函数时,必须保证传递的指针具有非零值,并且指向以null结束的字符数组中的第一个元素。对于会修改传入字符串的标准库函数,程序员必须确保目标字符串必须足够大,否则会产生严重错误。

正是存在很多缺陷,C++中推荐尽量使用标准库类型string来代替这些操作,提高安全性和效率。

 

以上就介绍了C/C+的相关知识,希望对C/C+有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程