Fork me on GitHub

C++ Primer Plus 学习笔记二

关于复合类型的一些内容

复合类型

数组

和C语言类似,C++中也可以创建数组。数组声明应指出以下3点:
·储存在每个元素中的值的类型;
·数组名;
·数组中的元素数;
和C语言类似,声明数组的通用格式如下:

1
2
3
typeName arrayName[arraySize];
//示例:
short months[12];

和C语言一致,数组从0开始编号。例如,months[0]是months数组的第一个元素。可以通过索引来标示和访问各个元素。

有效下标值

编译器不会检查使用的下标是否有效。在程序运行后,可能会引发问题。所以必须确保程序只使用有效的下标值。

数组的初始化

只有定义数组时才能使用初始化,此后就不能使用了,也不能进行数组间的赋值:

1
2
3
4
int cards[4] = {3, 6, 8, 10};	// okay
int hand[4]; // okay
hand[4] = {5, 6, 7, 9}; // not allowed
hand = cards; // not allowed

如果初始化时方括号内为空,则编译器将计算元素个数。

string类

ISO/ANSI C++98标准通过添加string类扩展C++库,因此现在可以用string类型的变量(C++称之为对象)而非字符数组来存储字符串。这使用起来比数组简单。
要使用string类,必须在程序中包含头文件string。string类位于名称空间std中,因此也需要使用using编译指令,或是std::string来引用。string类定义隐藏了字符串数组性质,因此可以像处理普通变量一样处理字符串。

赋值、拼接、附加

参看如下代码:

1
2
3
4
5
6
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
charr1 = charr2; // INVALID
str1 = str2; // VALID

string类简化了字符串的合并操作。在C语言中使用strcat(str1,str2)函数来进行拼接,且有诸多注意事项,但是string类则可以使用运算符+将两个string对象合并起来,也可以使用运算符+=将字符串附加到string对象的末尾。例如:

1
2
3
string str3;
str3 = str1 + str2; // assign str3 to the joined strings
str1 += str2; // add str2 to the end of str1

当然,C++中也可以使用C语言库中的函数来完成这些任务。头文件cstring(以前为string.h)中提供了这些函数:

1
2
strcpy(charr1, charr2);		// copy charr2 to charr1
strcat(charr1, charr2); // append contents of charr2 to charr1

当然,在VS2017的编译环境中,会采用更安全的strcpy_s,strcat_s函数。

结构

和C语言相同,C++也提供结构体,例如:

1
2
3
4
5
6
struct inflatable	// structure declaration
{
char name[20];
float volume;
double price;
}

此外,还有共用体(union,有时也叫做联合)、枚举(enum)等结构,在此便不赘述。

指针

熟悉C语言的都对指针有一定了解,我们在此便略过基础的知识。

使用new来分配内存

C语言中我们使用malloc()来分配内存,而在C++中,可以使用new运算符来进行。
下面来试试这种新技术,在运行阶段将一个int值分配未命名内存,并使用指针来进行访问。程序员需要告诉new,需要为哪种数据类型分配内存;new将找到一个正确的内存块,并返回该内存块的地址。程序员的责任是将其赋给一个指针,例如:

1
int * pn = new int;

new int告诉程序,需要适合储存int的内存。new运算符根据类型来确定需要多少字节的内存,它找到这样的内存并返回其地址。接下来,将地址赋给pn,pn是被声明为指向int的指针。现在,pn是地址,而*pn是春促在那里的值。将其与将变量的地址赋给指针进行比较:

1
2
int higgens;
int * pt = &higgens;

在这两种情况下,都是将一个int变量地址赋给了指针。在第二种情况下,可以用名称higgens来访问该int,在第一种情况下,只能通过该指针进行访问。这便引出了一个问题:pn指向的内存没有名称,如何称呼它呢?我们说pn指向一个数据对象(不是“面向对象编程”的对象,而是一样东西),术语“数据对象”比“变量”更为通用,它指的是为数据项分配的内存块。因此,变量也是数据对象,而pn指向的内存不是变量。乍一看,处理数据对象的指针方法可能不太好用,但它使程序在管理内存方面有更大的控制权。
为一个数据对象(可以是结构,也可以是基本类型)获得并制定分配内存的通用格式如下:

1
typeName * pointer_name = new typeName;

需要在两个地方制定数据类型。

使用delete来释放内存

在C语言中,一定会提到的便是malloc()之后,一定要有一个free()。这是为了避免程序将内存耗尽。C++中,使用delete运算符:

1
2
3
int * ps = new int;		// allocate memory with new
... // use the memory
delete ps; // free memory with delete when done

警告:只能使用delete来释放使用new分配的内存。然而,对空指针使用delete是安全的
不要尝试释放已经释放的内存块,这样做的结果将会是不确定的。另外,不能使用delete来释放声明变量所获得的内存
值得注意的是,使用delete的关键在于,将它用于new分配的内存。这并不意味着要使用用于new的指针,而是用于new的地址:

1
2
3
int * ps = new int;		// allocate memory
int * pq = ps; // set second pointer to same block
delete pq; // delete with second pointer

一般来说,不要创建两个指向同一个内存块的指针。因为这将增加错误删除同一个内存块两次的可能性。不过,在之后的学习中,将会学习到,对于返回指针的函数,使用另一个指针确实有道理。

0%