4.2 数组
定义 int arrName[size] 定义一个int 型的数组,数组长度为size;其中size必须为常量不能是变量。
例: int arr[10]
初始化:
int arr[] = {11, 12, 13, 14, 15}; 初始化为大小为5的数组。
int arr1[20] = {32, 33}; 剩下未初始化的18个编译器自动赋值0;
所以int arr2[10] = {0}; 可以将arr 全部初始化为0.
sizeof(arr):输出整个arr数组占用的字节空间,即4 * 5 = 20
sizeof(arr[0]) : 输出arr第一个下标 int型占用的字节大小,为4
数组未初始化,值是不确定的,即之前内存保存的数值
c++ 11 新增初始化话方法
int arr[10] {}; //可以不加 = 号; {} 中可以没有任何值,编译器全部初始化为0
字符串数组:
char arrstr[] = "HelloWorld!"; 长度未12 会自动加上结束符\0
char arrStr1[10] = {'a', 'b', 'b', 'v', 'b', 'f', 'h' }; 不是字符串
char arrStr1[10] = {'a', 'b', 'b', 'v', 'b', 'f', '\0' };是字符串
strlen() 为函数,计算字符串长度不包括\0
cin >> name;
cout << "Entor food: " << endl;
cin >> food;
cout << "name : " <<name << endl;
cout << "food : " <<food << endl;
如果直接输入的是 zhangsan apple
输出 name:zhangsan
food:apple
cin 先从输入流中读取zhangsan,加上\0,放入name数组中;然后读取apple,加上\0,放到food中。
getline()和get()函数
cin.getline(strline, 50); 将输入流的一行放入数组strline中,最多50字节。会将换行符替换为\0;
cin.get(strline, 50); 将输入流的一行放入数组strline中,最多50字节。不会替换换行符,换行符不会读取还是在输入流中,所以在此调用cin.get() 读取到的是换行符。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void start_array_text_fun();
int main()
{
cout << "Start main funtion!" << endl;
start_array_text_fun();
system("pause"); // 防止运行后自动退出,需头文件stdlib.h
return 0;
}
void start_array_text_fun() {
int arr[] = {11, 12, 13, 14, 15};
int arr1[20] = {32, 33};
cout << "arr size: " << sizeof(arr) << endl;
cout << "arr size: " << sizeof arr[0] << endl;
cout << "arr : " << *(arr+1) << endl;
char arrstr[] = "HelloWorld!";
cout << "arrstr : " << arrstr << endl;
cout << "sizeof arrstr : " << sizeof arrstr << endl;
int size = 20;
char arrnamr[size] = {'h', 'b'};
cout << "arrnamr : " <<sizeof arrnamr << endl;
char strline[100];
cin.getline(strline, 50);
cout << strline << endl;
}
4.3 string类型
string 为c++类
string str = “HelloWorld!”; 定义string类型的对象str,并赋值;str是实例化的对象
str.size() 计算长度,单位字节,不带\0
str1 += str2;连接两个字符串
str1 = str2;将str2 内容赋值到str1
strncpy(des, src)c风格的字符串赋值
strncat(char1, char2)c风格的字符串连接
4.4 结构体
定义结构体:
struct st_student {
char name[20];
int age;
int high;
};
定义结构体变量:
struct st_student stu1 = {"zhangsan", 10, 168};
st_student stu2 = {"lisi", 17, 178};
C++ 允许,定义结构体不加struct 关键字;c语言必须加;c语言可以通过typedef 关键字定义别名方法省略struct关键字。
初始化:
结构体初始化方式和数组类似
struct st_student stu1 {"zhangsan", 10, 168}; //可以省略 = 号
struct st_student stu1 {}; //括号没有值,将被初始化为全0
结构体赋值 stu1 = stu2;将stu2 所有成员赋值给stu1; 注意数组是不能直接这样赋值的
struct {
char name[20];
int age;
int high;
} stu; 定义一种结构体,没有名字,并定义变量stu,以后不能再定义其他的此种类型变量。
结构体的位字段:
struct bit_register {
unsigned int SN : 4; 位字段,表示占用4bit
unsigned int : 4;
bool power : 2;
bool enable : 1;
bool IN : 1;
} regist;
4.5 共同体
union id {
int identify;
char inden[10];
};
共用体的成员共用一块内存,所以同一时间只能存储一个成员,整个共用体的内存大小是共用体最大的成员占用的内存。
共用体是为了节省内存
匿名共用体
union wigdth {
int high;
char name[10];
union {
int identify;
char inden[10];
} prize;
};
由于union没有名字,所以调用是省略共用体名字:prize.identify
4.6 枚举类型
enum 提供了创建常量的一种方法,可以取代 const
enum weekday {Monday, Tuesday,Wednesday, Thursday, Friday};
其中 成员Monday都是枚举常量,代表从0 开始的整数
可以定义枚举变量 weekday day = Tuesday;
枚举变量必须用常量做初始化。
也可以自定义初始化
enum weekday {Monday = 1, Tuesday,Wednesday = 100, Thursday, Friday};
4.7 指针和自由存储空间
计算机存储数据三个基本要素:
1 信息存储在何处
2 存储的值
3 存储数据类型
指针声明:
int* p; 声明指针变量p 为指向int型的指针,指针p中存储的地址是一个int型数据的地址
p是 int* 型指针或int* 型,*p 是int型
int a = 1;
int* p = &a; 初始化,将a的地址保存到指针变量p
指针的真正用途:在运行阶段分配未命名的内存以存储值。
new运算符:
int* pn = new int; new根据类型int。自己找到一个长度正确的内存块,返回给pn。
通用格式:typename* pointer_name = new typename ;
//typename可以是基本类型,也可以是结构等。
int a;局部变量存储在函数栈内,包块指针pn;但是new 申请的内存和malloc函数一样,是存储在堆(heap)上或自用存储区的内存区域。
delete运算符
int* ps = new int;
delete ps; 释放ps指向的内存
注意:必须配对使用new 、delete;出现new 一定要有delete,避险造成内存泄漏。
delete不能重复释放;不能释放声明的变量:int ia = 10;delete ia;//不合法
动态数组
int arr[10]; //静态联编,系统在编译阶段创建一个静态数组,内存也是在编译阶段分配。
int* parr = new int[10]; //动态联编,系统在运行阶段为数组创建内存。 数组长度可以动态选择。
parr[1]; 等价于 *(parr + 1);
delete [] parr; 释放数组
注意:
1 不能使用delete释放不是new的内存
2 不能使用delete释放通意块内存两次
3 使用new[] 申请的内存,要用delete[] 释放内存
指针数组,数组地址
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
arr 代表数组第一个元素的地址,等价于 &arr[0] , arr +1 相当于将指针移向第二个元素,即地址加上指针类型int的内存大小。可以将arr当作 int* 型
&arr 为整个数组的地址,&arr +1 相当于将指针移动到下一个int[10] 的数组,即&arr +1 == arr + sizeof(int)* 10; &arr可以当作 int[10] * 型,即指向10个int数据大小的数组的指针。
定义数组指针 int (*p)[10] = &arr; //p是一个数组指针,p指向大小为10 的int型数组。
注意数组大小[10] 必须指定,因为编译器必须知道,这个指针是指向多大的数组的。
所以*p == *(&arr)== arr; **p == arr[0] == *(arr+0) ; *(*p +1) == *(arr +1)
创建动态数组:
struct thing {
int good;
int bad;
};
thing* p = new thing;
利用指针引用成员: p->good;
自动存储、静态存储、动态存储
自动存储:就是函数局部变量所占用的内存,在函数栈上,函数结束时会自动释放,作用域为大括号范围,大括号结束时释放。内存释放和申请顺序相反,后进先出。
静态存储:函数外定义和函数内且使用static声明的变量称为静态存储变量,生命周期为整个程序周期,存储在静态存储区域。
动态存储:使用new (c的 malloc)申请的内存称为动态存储,程序在堆中申请内存,可以delete动态的释放。如果不及时delete 会造成内存泄漏。
指针数组:
thing mthing1;
thing mthing2;
const thing * arrthing[2] = { mthing1, mthing2};
thing ** p = arrthing;
arrthing 是一个指针数组,数组里存储的都是thing*型指针,引用成员:arrthing[0]->good;
p是一个指向指针数组的指针,因为p指向arrthing的第一个成员mthing1地址,mthing1是一个thing*型,所以p要声明成指向thing*型的指针,即thing** p;
引用成员,*(p+1)->bad; 等价于 arrthing[1]->bad;
vector、array
vector:
vector是STL的动态数组,属于模板类,可以在运行中根据需要改变数组的大小。因为它以数组的形式储存,所以它的内存空间是连续的。vector的头文件为#include<vector>
定义一个动态数组: vector<int> arr(100); arr 是一个vector<int>型,内部有100个int数据
可以向数组一样使用 arr[10] = 10;
常用方法:
1.vector<int>a 创建一个动态数组a,a的默认初值为0
2.vector<int >b(a) 将a中的元素复制到b中
3.vetcor<int>a(100) 将数组a的元素定义为100个,默认初始值为0
4.vector<int>a(100,6) 定义100个值为6的元素
5.vector<string>a(10,"null") 定义10个值为null的元素
6.vector<string>a(10,"hello") 定义10个值为hello的元素
7.vector<string>b(a.begin(),a.end()) 将动态数组a的元素值复制到b中
常用操作:
1.a.push_back(100) 在尾部加入一个值为100的元素
2.a.size() 返回数组中元素的个数
3.bool isEmpty=a.empty() 判断a是否为空,若为空返回true,若不为空则返回false
4.cout<<a[0]<<endl 输出数组的大小
5.a.insert(a.begin+i,k) 在第i个元素前插入k
6.a.insert(a.end(),10,5) 在末尾插入10个值为5的元素
7.a.pop_back 删除末尾元素
8.a.erase(a.begin()+i,a.begin()+j) 将[i,j-1]的元素都删除
9.a.erase(a.begin()+i) 将第i+1个元素删除
10.a.resize(n) 将数组重置为n个元素
11.a.clear() 清空数组
12.reverse(a.begin(),a.end()) 将数组逆转
13.sort(a.begin(),a.end()) 将数组从小到大排序
array:
vector 是在堆中动态申请内存,程序自动释放;效率相比数组要低;
array和数组一样,再栈中申请内存。
定义方法 array<int, 10> arr; 创建大小为10的 int array 对象。第二个参数是固定的不能是变量。
所有array对象的大小是固定的。
array 模板类可以直接赋值,arr1 = arr2;注意 数组是不可以的,只能一个一个复制;