C++ Primer Plus 学习笔记(第 4 章 复合类型)
C++ Primer Plus 学习笔记
第 4 章 复合类型
数组
数组(array)是一种数据格式,能够存储多个同类型的值。
要创建数组,可使用声明语句。数组声明应指出以下三点:
- 存储在每个元素的值的类型;
- 数组名;
- 数组中的元素数。
声明数组的通用格式如下:
typename arrayName[arraySize];
表达式arraySize
指定元素数目,必须是整数或const
值,也可以是常量表达式,即其中所有的值在编译时都是已知的,即不能是变量。
使用下标或索引访问元素,C++数组从0
开始编号。编译器不会检查使用的下标是否有效。
数组的初始规则
只有在定义数组时才能使用初始化,此后就不能使用了,也不能将一个数组赋给另一个数组。
然而,可以使用下标分别给数组中的元素赋值。
初始化数组时,提供的值可以少于数组的元素数目。
如果只对数组的一部分进行初始化,则编译器将把其他元素设置为0
。
如果初始化数组时方括号内为空,C++编译器将计算元素个数。此方法对将字条数组初始化为一个字符串来说比较安全。
C++11 数组初始化方法
C++11将使用大括号的初始化(列表初始化)作为一种通用的初始化格式,可用于所有类型。
数组以前就可以使用列表初始化,但C++11中的列表初始化新增了一些功能。
首先,初始化数组时,可以省略等号(=
)。
其次,可不在大括号内包含任何东西,这将把所有元素都设置为零。
第三,列表初始化禁止缩窄转换。
字符串
字符串是存储在内存的连续字节中的一系列字符。C++处理字符串的方式有两种。第一种来自C语言,常被称作C-风格字符串(C-style string)。另一种是基于string
类库的方法。
C-风格字符串具有一种特殊的性质:空字符(null character)结尾,空字符实写作\0
,其ASCII码为0
,用来标记字符串的结尾。
将字符数组初始化为字符串的方法——只需使用一个引号括起的字符串即可,这种字符串被称为字符串常量(string constant)或字符串字面值(string literal)。
用引号括起的字符串常量隐式地包括结尾的空字符,因此不用显示地包括它。
注意:字符串常量(使用双引号)不能与字符常量(使用单引号)互换。
拼接字符串常量
C++允许拼接字符串字面值,任何两个由空白(空格、制表符和换行符)分隔的字符串常量都将自动拼接成一个。
注意:拼接时不会在被连接的字符串之间添加空格,第一个字符串中的\0
字符将被第二个字符串的第一个字符取代。
在数组中使用字符串
要将字符串存储到数组中,最常用的方法有两种——将数组初始化为字符串、将键盘或文件输入读入到数组中。
字符串输入
cin
使用空白(空格、制表符和换行符)来确定字符串的结束位置。
每次读取一行字符串输入
iostream
中的类(如cin
)提供了一些面向行的类成员函数:getline()
和get()
。这两个函数都读取一行输入,直到到达换行符。然而,随后getline()
将丢弃换行符,而get()
将换行符保留在序列中。
面向行的输入getline()
cin.getline(charArray, strSize);
getline()
函数每次读取一行,最多读取strSize-1
个字符,通过换行符确定行尾,但不保存换行符,存储时用空字符代替换行符。
面向行的输入get()
get()
第一种工作方式与getline()
类似,接受相同的参数,但不再丢弃换行符,而是将它保留在输入序列中。不带参数即可读取一个字符,包括换行符。
cin.get(charArray, strSize);
cin.get();
另一种使用get()
的方式是将两个类成员函数拼接起来(合并),getline()
也可以,其效果与两次调用相同。
cin.get(charArray, strSize).get();
cin.getline(charArray1, strSize).getline(charArray2, strSize);
空行和其他问题
当get()
读取空行后新塘镇设置失效位,接下来的输入被阻断,可使用cin.clear();
恢复输入。
如果输入行包含的字符数比指定的多,则getline()
和get()
将把余下的字符保留在输入队列中,而get()
还会设置失效位,并关闭后面的输入。
混合输入字符串和数字
在cin
读取数字后,在getline()
之前要丢弃换行符,可使用没有参数的get()
。
string 类简介
C++98标准通过添加string
类扩展了C++库,可以使用string
类型的对象来存储字符串。string
类使用起来比数组简单,同时提供了将字符串作为一种数据类型的表示方法。
要使用string
类,必须在程序中包含头文件string
。string
类位于名称空间std
中,因此必须提供一条using
编译指令,或使用std::string
来引用它。string
类定义隐藏了字符串的数组性质,可像普通变量那样处理字符串。
在很多方面,使用string
对象的方式与使用字符数组相同。
- 可以使用C-风格字符串来初始化
string
对象。 - 可以使用
cin
来将键盘输入存储到string
对象中。 - 可以使用
cout
来显示string
对象。 - 可以使用数组表示法来访问存储在
string
对象中的元素。
string
对象与字符数组之间的主要区别是,可以将string
对象声明为简单变量,而不是数组。
类设计让程序能够自动处理string
的大小。这使用与使用数组相比,使用string
对象更方便,也更安全。
未被初始化的string
对象的长度被自动设置为0
。
C++11 字符串初始化
C++11也允许将列表初始化用于C-风格字符串和string
对象。
赋值、拼接和附加
不能将一个数组赋给另一个数组,但可以将一个string
对象赋给另一个string
对象。
可以使用运算符+
将两个string
对象合并起来,还可以使用运算符+=
将字符串附加到string
对象的末尾。
可以将C-风格字符串或string
对象与string
对象相加,或将它们附加到string
对象的末尾。
str3 = str1 + str2; // string类对象拼接
strcpy(charr3, charr1); // C-风格字符串函数copy
strcat(charr3, charr2); // C-风格字符串函数cat
int int1 = str1.size(); // string类方法
int int2 = strlen(charr1); // C-风格字符串函数
strlen()
是一个常规函数,size()
是一个类方法。
string 类 I/O
可以使用cin
和运算符>>
来将输入存储到string
对象中,也可以使用cout
和运算符<<
来显示string
对象,其句法与C-风格字符串相同。但每次读取一行而不是一个单词时,使用的句法不同。
cin.getline(charry, 20); \\类方法
getline(cin, str); \\不是类方法
在引入string
类之前,C++就有了iostream
类,所以iostream
没有处理string
对象的类方法。
其他形式的字符串字面值
创建wchar_t
、char16_t
和char32_t
的字符串常量时,C++分别使用前缀L
、u
和U
表示。
C++11还支持Unicode字符编码方案UTF-8,使用前缀u8
来表示。
C++新增的另一种类型是原始(raw)字符串,在原始字符串中,字符表示的就是自己。
原始字符串将"(
和)"
用作界定符,并使用前缀R
来标识原始字符串。可以在默认界定符之间添加任意数量的基本字符,但空格、左括号、右括号、斜杠和控制字符(如制表符和换行符)除外。
可将前缀R
与其他字符串前缀结合使用,以标识wchar_t
等类型的原始字符串。可将R
放在前面,也可以放在后面,如Ru
、UR
等。
结构简介
结构是用户定义的类型,创建结构包括两步。首先,结构声明——定义这种类型的数据属性;然后,按描述创建结构变量(结构数据对象)。
struct type_name {member_type1 member_name1;member_type2 member_name2;member_type3 member_name3;......
};
type_name object_names;
object_names.nember_name1;
C++允许在声明结构变量时省略关键字struct
,可以使用成员运算符.
来访问成员。访问类成员函数的方式是从访问结构成员变量的方式衍生而来的。
在程序中使用结构
结构声明的位置很重要。外部声明可以被其后面的任何函数使用,而内部声明只能被该声明所属的函数使用。通常应使用外部声明,这样所有的函数都可以使用这种类型的结构。
变量也可以在函数内部和外部同义,外部变量由所有的函数共享。C++不提倡使用外部变量,但提倡使用外部结构声明。另外,在外部声明符号常量通常更合理。
C++11 结构初始化
首先,C++11也支持将列表初始化用于结构,且等号=
是可选的。
其次,如果大括号内未包括任何东西,各个成员都将被设置为零。
最后,不允许缩窄转换。
结构可以将 string 类作为成员
一定要让结构定义能够访问名称空间std
,为此,可以将using
编译指令移到结构定义之前,也可以使用类型声明std::string
。
其他结构属性
C++使用户定义的类型与内置类型尽可能相似。例如,可以将结构作为参数传递给函数,也可以让函数返回一个结构。另外,还可以使用赋值运算符=
将结构赋给另一个同类型的结构,即使成员是数组,这种赋值被称为成员赋值。
可以同时完成定义结构和创建结构变量的工作,只需将变量名放在结束括号后面即可,甚至可以初始化以这种方式创建的变量。
然而,将结构定义与变量声明分开,可以使用程序更易于阅读和理解。
还可以声明没有名称的结构类型,方法是省略名称,同时定义一种结构类型和这一个这种类型的变量。但这种类型没有名称,因此以后无法再创建这种类型的变量。
结构数组
可以创建元素是结构的数组,方法和创建基本类型数组完全相同。其中每个元素可以与成员运算符一起使用。
要初始化结构数组,可以结合使用初始化数组的规则(用逗号分隔每个元素,并将这些值用花括号括起来)和初始化结构的规则(用逗号分隔每个成员的值,并将这些值用花括号括起来)。
结构中的位字段
与C语言一样,C++也允许指定占用特定位数的结构成员,这使得创建与某个硬件设备上的寄存器对应的数据结构非常方便。字段的类型就为整数或枚举,接下来是冒号,冒号后面是一个数字,指定使用的位数。也可以使用没有名称的字段来提供间距。每个成员都被称为位字段(bit field)。
struct torgle_register
{unsigned int SN : 4;unsigned int : 4;bool goodIn : 1;bool goodTorgle : 1;
};
torgle_register tr = { 14, true, false };
if (tr.goodIn)
位字段通常用在低级编程中。一般来说,可以使用整型和按位运算符来代替这种方式。
共用体
共用体(union)是一种数据结构,它能够存储不同的数据类型,但只能同时存储其中的一种类型。
union one4all
{int int_val;long long_val;double double_val;
};
可以使用one4all变量来存储int、long或double,条件是在不同的时间进行。
由于共用体每次只能存储一个值,因此它必须有足够的空间来存储最大的成员,所以,共用体的长度为最大成员长度。
共用体的用途之一是,当数据项使用两种或更多种格式(但不会同时使用)时,可节省空间。例如,假设管理一个小商品目录,其中有一些商品ID为整数,而另一些的ID为字符串。在这种情况下,可以这样做。
struct widget
{char brand[20];int type;union id{long id_num;char id_char[20];}id_val;
};
...
widget prize;
...
if(prize.type == 1)cin >> prize.id_val.id_num;
elsecin >> prize.id_val.id_char;
匿名共用体没有名称,其成员将成为位于相同地址的变量。显然,每次只有一个成员是当前的成员:
struct widget
{char brand[20];int type;union{long id_num;char id_char[20];};
};
...widget prize;
...if(prize.type == 1)cin>>prize.id_num;
elsecin>>prize.id_char;
由于共用体是匿名的,因此id_num
和id_char
被视为prize
的两个成员,它们的地址相同,所以不需要中间标识符id_val
。程序员负责确定当前哪个成员是活动的。
共用体常用于(但并非只用于)节省内存。C++还常用于嵌入式系统编程,如控制烤箱、MP3播放器或火星漫步者的处理器。对这些应用程序来说,内存可能非常宝贵。另外,共用体还常用于操作系统数据结构或硬件数据结构。
枚举
C++的enum
工具提供了另一种创建符号常量的方式,可以代替const
。它还允许定义新类型,但必须按严格的限制进行。使用enum
的句法与使用结构相似。
enum color_set1 {RED, ORANGE, YELLOW, GREEN, BLUE, WHITE, BLACK};
将RED
、ORANGE
、 YELLOW
等作为符号常量,叫做枚举量。
在默认情况下,将整数赋给枚举量,从0
开始。也可通过显式地指定整数值来覆盖默认值。
可能用枚举名来声明这种类型的变量。
在不进行强制类型转换的情况下,只能将定义枚举时使用的枚举量赋给这种枚举变量。
对于枚举,只定义了赋值运算符,没有为枚举定义算术运算。可以在算术表达式中同时使用枚举和常规整数,枚举将转换为整数。
如果整数值是有效的,则可通过强制类型转换,将它赋给枚举变量。
实际上,枚举更常被用来定义相关的符号常量,而不是新类型。如果打算只使用常量,而不创建枚举变量,则可以省略枚举类型的名称。
设置枚举量的值
可以使用赋值运算符来显式地设置枚举量的值,指定的值必须是整数。也可以只显式地定义其中一些枚举量的值,没有被显式定义的枚举量的值将比其前面的枚举量大1
。
可以创建多个值相同的枚举量。
枚举的聚会范围
最初,对于枚举来说,只有声明中指出的那些值是有效的。然而,C++现在通过强制类型转换,增加了可赋值给枚举变量的合法值。每个枚举都有取值范围(range),通过强制类型转换,可以将取值范围中的任何整数值赋给枚举变量,即使这个值不是枚举值。
取值范围的定义如下。
首先,要找出上限,需要知道枚举量的最大值。大于这个最大值的、最小的2
次幂减1
,就是取值范围的上限。
要计算下限,需要知道枚举量的最小值。如果不小于0
,则取值范围的下限就是0
;否则,采用与寻找上限相同的方法,但加上负号。
选择多少空间来存储枚举由编译器决定。
指针和自由存储空间
指针是一个变量,其存储的是值的地址,而不是值本身。
对变量应用地址运算符&
,可以获得它的地址。
使用常规变量时,值是指定的量,而地址为派生量。
使用指针变量时,将地址视为指定的量,而将值视为派生量。
指针名表示地址,*
运算符被称为间接值或解除引用运算符,将其用于指针,可以得到该地址外存储的值。
声明和初始化指针
指针声明必须指定指针指向的数据的类型。
int * p1, * p2;
int higgens = 5;
int * pt = &higgens;
*
运算符两边的空格是可选的。对每个变量,都需要使用一个*
。
可以在声明语句中初始化指针。
指针的危险
在C++创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。
警告:一定要在对指针应用解除引用运算符*
之前,将指针初始化为一个确定的、适当的地址。
指针与数字
指针不是整型,不能简单地将整型同给指针,应通过强制类型将数字转换为适当的地址类型。
int * pt = (int *)0xB0000000;
使用 new 来分配地址
将指针初始为变量的地址,变量是在编译时分配的有名字的地址,指针只是可以通过名称直接访问的地址提供了一个别名。
指针真正的用武之地在于,在运行阶段分配未命名的内存以存储值。在这种情况下,只能通过指针来访问内存。
C++用new
运算符来分配内存。
int * pt = new int;
new
运算符根据类型来确定需要多少字节的内存,然后,找到这样的内存,并返回其地址。
我们说pt
指向一个数据对象,它指的是为数据项分配的地址,因此,变量也是数据对象,但指向的内存不是变量。
在C++中,值为0
的指针被称为空指针(null pointer)。C++确保空指针不会指向有效的数据。C++提供了检测并处理内存失败的工具。
使用 delete 释放内存
使用deltet
运算符,能在使用完内存后,将其归还给内存池,归还或释放(free)的内存可供程序的其他部分使用。
使用deltet
时,后面要加上指向内存块的指针(这些内存块最初是用new
分配的。
int * pt = new int;
...
delete pt;
deltet
释放内存,但不会删除指针。
一定要配对使用new
和deltet
,否则将发生内存泄露(memory leak),即被分配的内存再也无法使用。
不要尝试释放已经释放的内存块,C++标准指出,这样做的结果将是不确定的。也不能用deltet
来释放声明变量所获得的内存。
只能用deltet
来释放使用new
分配的内存,但对空指针使用deltet
是安全的。
注意:使用deltet
的关键在于,将它用于new
分配的内存。这并不意味着要使用用于new
的指针,而是用于new
的地址。
使用 new 来创建动态数组
通过声明创建数组,在编译时给数组分配内存,称为静态联编。使用new
时,在需要的时候创建数组,还可选择数组的长度,这称为动态联编。这种数组叫做动态数组。
使用 new 创建动态数组
创建动态数组,要将数组的元素类型和元素数目告诉new
。必须在类型名后加上方括号,其中包含元素数目。
type_name * point_name = new type_name [num_elements];
delete [] point_name;
new
运算符返回第一个元素的地址。delete
后的方括号表示释放整个数组。不能使用sizeof
运算符来确定动态分配的数组包含的字节数。
使用new
和delete
时,应遵循的规则:
- 不要使用
delete
来释放不是new
分配的内存。 - 不要使用
delete
释放同一个内存块两次。 - 如果使用
new []
为数组分配内存,则应使用delete []
来释放。 - 如果使用
new []
为一个实体分配内存,则应使用delete
(没有方括号)来释放。 - 对空指针应用
delete
是安全的。
使用动态数组
只有把指针当作数组名,使用索引访问元素。原因是C和C++内部都使用指针处理数组。
不能修改数组名的值,但指针是变量,因此可以修改指针的值。
指针、数组和指针算术
指针变量加1
后,增加的变量等于它指向的类型的字节数。
C++将数组名解释为指针,多数情况下,将数组名解释为数组第一个元素的地址。
在很多情况下,可以相同的方式使用指针名和数组名。可使用数组方括号表示法,也可以使用解除引用运算符*
。在多数表达式中,它们都表地址,区别之一是,可以修改指针的指,而数组名是常量。另一个区别是,数组应用sizeof
运算符得到的是数组的长度,对指针应用sizeof
得到的是指针的长度,即使指针指向的是一个数组。
这种情况下,C++不会将数组名解释为地址。
对数组名取地址时,数组名也不会被解释为地址,这样得到的是整个数组的地址。
指针小结
要声明指向特定类型的指针,使用如下格式:
typeName * pointName;
应将内存地址赋给指针,可以对变量名应用&
运算符,来获得被命名的内存的地址,new
运算符返回未命名的内存的地址。
对指针解除引用意味着获得指针指向的值,对指针应用解除引用或间接值运算符*
来解除引用。
另一种对指针解除引用的方法是使用数组表示法。
在多数情况下,C++将数组名视为数组的第一个元素的地址。一种情况例外是,将sizeof
运算符用于数组名时,此时返回整个数组的长度。
C++允许将指针与整数相加。相加的结果等于原来的地址加上指向的对象占用的总字节数。还可以两个指针相关,得到一个整数,仅当两个指针指向同一个数组(也可以指向超出结尾一个位置)时,这种运算才有意义,这将得到两个元素的间隔。
使用数组声明来创建数组时,将采用静态联编,即数组的长度在编译时设置。
使用new []
运算符创建数组时,将采用动态联编(动态数组),即将在运行时为数组分配内存,其长度也在运行时设置。使用完这种数组后,应使用deldte []
释放其占用的内存。
使用方括号数组表示法等同于对指针解除引用。
指针和字符串
注意:在cout
和多数C++表达式中,char
数组名、char
指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址。
- 有些编译器将字符串字面值视为只读常量,不能修改。在C++中,字符串字面值都被视为常量。
- 有些编译器只使用字符串字面值的一个副本来表示程序中的有的该字面值。C++不能保证字符串字面值被唯一地存储。
不要使用字符串常量或示被初始化的指针来接收输入。
注意在将字符串读入程序时,应使用已分配的内存地址。该地址可以是数组名,也可以是使用new
初始化过的指针。
strcpy(pt, charry);
strncpy(pt, "sentences", num);
strcpy()
函数接受2个参数,第一个是目标地址,第二个是要复制的字符串的地址。
strncpy()
函数还接受第3个参数——要复制的最大字符数。
警告:应使用strcpy()
和strncpy()
,而不是赋值运算符来将字符串赋给地址。
使用 new 创建动态结构
需要在程序运行时为结构分配所需的空间,也可使用new
运算符来完成,创建动态结构。由于类与结构非常相似,所以本节有关结构的技术也适用与类。
将new
用于结构需要两步:创建结构和访问其成员。
要创建结构,需要同时使用结构类型和new
,将地址赋给指针。
创建动态结构时,不能使用成员运算符,因为这种结构没有名称只有地址,C++提供了一个运算符:箭头成员运算符->
用于指向结构的指针,就像点运算符可用于结构名称一样。
另一种访问结构成员的方法是,如果ps
是指向结构的指针,则*ps
是被指向的值——结构本身,因此(*ps).price
是该结构的成员。C++的运算优先规则要求使用括号。
自动存储、静态存储和动态存储
C++有三种管理数据内存的方式:自动存储、静态存储和动态存储(有时也叫作自由存储空间或堆)。C++11新增了第四种类型——线程存储。
自动存储
在函数内部定义的常规变量使用自动存储空间,被称为自动变量,在所属的函数被调用时自动产生,在该函数结束时消亡。
自动变量是一个局部变量,其使用域为包含它的代码块。
自动变量通常存储在栈中,执行代码块时,其中的变量依次加入栈中,而离开代码块时,将按相反的顺序释放这些变量,这被称为后进先出(LIFO)。
静态存储
静态存储是整个程序执行期间都存在的存储方式。使变量成为静态的方式有两种:一种是在函数外面定义它;另一种是在声明变量时使用关键字static
。
C++实现还不支持对自动数组和自动结构的初始化。
动态存储
new
和delete
运算符管理了一个内存池,这在C++中被称为自由存储空间(free store)或堆(heap)。该内存池与静态变量和自动变量的内存是分开的。在栈中,自动添加和删除机制使得占用的内存总是连续的,但new
和delete
的相互影响可能导致占用的自由内存区不连续。
数组的替代品
模板类vector
和array
是数组的替代品。
模板类 vector
模板类vector
类似于string
类,也是一种动态数组。它是使用new
创建动态数组的替代品,实际上vector
类确实是使用new
和delete
来管理内存,但其工作是自动完成的。
首先,使用vector
对象,必须包含头文件vector
。
其次,vector
包含在名称空间std
中,因此要使用using
编译指令、using
声明或std::vector
。
第三,模板使用不同的语法来指出它存储的数据类型。
第四,vector
类使用不同的语法来指定元素数。
vector<typeName> vt(n_elem);
创建一个名为vt
的vector
对象,可存储n_elem
个类型为typeName
的元素,其中参数n_elem
可以是整型常量,也可以是整型变量。
模板类 array(C++11)
vector
类的功能比数组强大,但付出的代价是效率低。如果需要长度固定的数组,使用数组是更佳选择,但代价是不那么方便和安全。
C++11新增了模板类array
,它也位于名称空间std
中。与数组一样,array
对象的长度也是固定,也使用栈(静态内存分配),而不是自由存储区,因此效率与数组相同,但更方便,更安全。要创建array
对象,需要包含头文件array
。
array<typeName, n_elem> arr;
创建一个名为arr
的array
对象,可包含n_elem
个类型为typeName
的元素,其中参数n_elem
是整型常量,不可以是整型变量。
比较数组、vector 对象和 array 对象
首先,数组、vector
对象和array
对象,都可以使用标准数组表示法来访问各个元素。
其次,array
对象与数组存储在栈中,而vector
对象存储在自由存储区或堆中。
第三,可以将一个array
对象赋给另一个array
对象;而对于数组,必须逐元素复制数据。
使用中括号表示法时,C++不检查索引是否非法,而vector
对象和array
对象的成员函数at()
将在运行期间捕获非法索引,而程序默认将中断。这种额外检查的代价是运行时间更长,这就是C++允许任何一种表示法的原因所在。它们包含成员函数begin()
和end()
,能够确定边界。
第 4 章总结
数组、结构和指针是C++的3种复合类型。数组可以在一个数据对象中存储多个同种类型的值。通过
使用索引或下标,可以访向数组中各个元素。
结构可以将多个不同类型的值存储在同一个数据对象中,可以使用成员关系运算符.
来访问其中的
成员。使用结构的第一步是创建结构模板,它定义结构存储了哪些成员。模板的名称将成为新类型的标识符,然后就可以声明这种类型的结构变量。
共用体可以存储一个值,但是这个值可以是不同的类型,成员名指出了使用的模式。
指针是被设计用来存储地址的变量。我们说,指针指向它存储的地址。指针声明指出了指针指向的对
象的类型。对指针应用解除引用运算符,将得到指针指向的位置中的值。
字符串是以空字符为结尾的一系列字符。字符串可用引号括起的字符串常量表示,其中隐式包含了结
尾的空字符。可以将字符串存储在char
数组中,可以用被初始化为指向字符串的char
指针表示字符串。函数strlen()
返回字符串的长度,其中不包括空字符。函数strcpy()
将字符串从一个位置复制到另一个位置。在使用这些函数时,应当包含头文件cstring
或string.h
。
头文件string
支持的C++strimg
类提供了另一种对用户更友好的字符串处理方法。具体地说,string
对象将根据要存储的字符串自动调整其大小,用户可以使用赋值运算符来复制字符串。
new
运算符允许在程序运行时为数据对象请求内存。该运算符返回获得内存的地址,可以将这个地址
赋给一个指针,程序将只能使用该指针来访问这块内存。如果数据对象是简单变量,则可以使用解除引用运算符(*)来获得其值;如果数据对象是数组,则可以像使用数组名那样使用指针来访问元素;如果数据对象是结构,则可以用指针解除引用运算符->
来访问其成员。
指针和数组紧密相关。如果ar
是数组名,则表达式ar[i]
被解释为*(ar+i)
,其中数组名被解释为数组第一个元素的地址。这样,数组名的作用和指针相同。反过来,可以使用数组表示法,通过指针名来访问new
分配的数组中的元素。
运算符new
和delete
允许显式控制何时给数据对象分配内存,何时将内存归还给内存池。自动变量是在函数中声明的变量,而静态变量是在函数外部或者使用关键字static
声明的变量,这两种变量都不太灵活。自动变量在程序执行到其所属的代码块(通常是函数定义)时产生,在离开该代码块时终止。静态变量在整个程序周期内都存在。
C++98新增的标准模板库(STL)提供了模板类vector
,它是动态数组的替代品。C++11提供了模板
类array
,它是定长数组的替代品。
C++ Primer Plus 学习笔记(第 4 章 复合类型)相关推荐
- 《Go语言圣经》学习笔记 第四章 复合数据类型
<Go语言圣经>学习笔记 第四章 复合数据类型 目录 数组 Slice Map 结构体 JSON 文本和HTML模板 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. ...
- c++primer plus 6 读书笔记 第四章 复合类型
目录 第4章复合类型 4.1 数组 4.1.1 4.1.2 数组的初始化规则 4.1.3C ++数组初始化方法使用{} 赋值,禁止缩窄转换. 4.2 字符串 4.2.1 拼接字符串常量 4.2.2 在 ...
- 《C++Primer》学习笔记(6-10章)
第六章 语句 1. if (int i = 3) // i转化成bool值true; 迄今为止,在所有用过的类型中,IO类型可以用作条件,vector和string类型一般不可用作条件 上面,出了if ...
- 《C++Primer》学习笔记(11-12章)
第十一章 算法 1. size_t <cstddef> back_inserter <iterator> 2. 提到的算法 find(vec.begin(), ...
- C Primer Plus 学习笔记 第7章 C控制语句:分支和跳转
继续写博客,趁着这几天印象还不错抓紧结束. 全书共分17章,这是关于本书第7章内容的博客,本章主要介绍了分支语句和跳转语句,还介绍了一些运算符.博客的目录和书上目录是相似的.此系列博客的代码都在Vis ...
- C++ Primer Plus 学习笔记 第四章 04编程练习
1. #include<iostream>int main() {using namespace std;cout<<"What is your first name ...
- C++Primer Plus笔记——第四章 复合类型及课后编程练习答案
目录 本章小结 程序清单 课后编程习题答案 本章小结 本章主要论述了数组.指针和引用.在C + +语言中,它们是相互交织在一起的,对其中一个概念的理解有助于对其他槪念的理解. 数组是一个由 ...
- Free Pascal 学习笔记 第五章 字符类型 Character Types
一.Char类型 一个字符一个字节,包含一个ASCII字符. Char类型通过将字符括在单引号中来指定字符常量,如'a' 'A' 二.WideChar 2个字节大小. 包含UTF-16编码的Unico ...
- 整理:C primer plus 学习笔记
前言:简单看了一遍C Primer Plus, 整理了一下,因为时间比较少,自己理解地比较肤浅,所以第一版比较简陋. 假期的时候应该会有时间再整理一下.------2018/11/5 2019/1/2 ...
最新文章
- php字符串加密解密源码,PHP中加密解密字符串函数源代码
- 各模组相关interface
- julia(4)-if ,else
- 如何减小电压跟随器输出电阻_机器人如何保护电池的电源管理系统 免受热坏?(附:PDF文档下载)...
- boost::ratio_string相关的测试程序
- 8字箴言:尊重、尽责、开放、创新
- dell c6220II lsi阵列卡
- 【TensorFlow】:解决TensorFlow的ImportError: DLL load failed: 动态链接库(DLL)初始化例程失败...
- 3. 什么是icmp?icmp与ip的关系_你知道如何跟女生,确定恋人关系吗?
- 使用oracle 的 PL/Sql 定时执行一个存储过程
- JavaScript 通过身份证号获取出生日期、年龄、性别 、籍贯
- matlab 汽车 仿真,MATLAB编程与汽车仿真应用
- 基于W800的AIOT离在线一体方案说明 (阿里飞燕+离线语音控制)
- 饿了么api接口 php,饿了么接口:php
- 上帝永远不会问你的十件事
- 基于Javafx制作的随机抽签软件
- 为什么相敬如宾是对的?
- 股票学习-量柱和k线-第六天
- b2g process 和nuwa process 通信
- 基于Epoll的Reactor模式