和Java一样,C++也有自己的容器,主要分为序列式容器和关联式容器,序列式容器主要分为Vector、list、dequeue(双端队列)、stack(栈)、queue(队列)、prority_queue(优先队列);关联式容器:set(集合)、map(键值对)、红黑树。
序列式容器:元素排列的顺序和元素本身无关,是根据元素添加的顺序排列
1、vector(先进后出)
(1)初始化
vector<int> vc1;
//声明有一个元素的空间
vector<int> vc2(1);
//6个元素,值都是1
vector<int> vc3(6, 1);
//构造方法,一个对象初始化另一个对象
vector<int> vc4(vc3);
(2)增删改查
vc1.push_back(10);
vc1.push_back(20);
vc1.pop_back();
cout << vc1[0] << endl;
通过push_back
来往vector
容器中添加元素,使用pop_back
删除尾部的元素,使用下标来获取容器中的元素。
获取队首元素:front
;
获取队尾元素:back
。
cout << vc1.front() << endl;
cout << vc1.back() << endl;
删除全部的元素:
vc1.clear();
vc1.erase(vc1.begin(), vc1.end());
(3)vector的容量
对于vector来说,它的容量是只增不减的,即便是将数据全部删除。
vector<int> vec;
void test() {
vec.push_back(10);
vec.push_back(20);
vec.clear();
cout << vec.capacity() << endl;
}
这个时候,它获取的容量还是2,如果想要将容器清零,需要使用swap
。
void test() {
vec.push_back(10);
vec.push_back(20);
vec.clear();
vector<int> v;
v.swap(vec);
cout << vec.capacity() << endl;
}
这个时候,容量已经是0.
2、queue
队列是一个先进先出的容器。
queue<int> q;
//添加元素
q.push(2);
q.push(4);
//弹出队列
q.pop();
3、stack
栈和Java中的栈是一致的,是先进后出的容器。
stack<int> stack;
stack.push(12);
stack.push(8);
stack.pop();
4、proprity_queue
优先级队列,默认情况下是添加的数据的最大值在队列头部。
priority_queue<int> qu;
qu.push(2);
qu.push(1);
qu.push(3);
cout << qu.top() << endl;
这个时候,最大值就是在对首。
如果想要声明最大和最小的数据所在的位置,就需要通过proprity_queue的重载方法实现。
priority_queue<int, vector<int>, less<int>> quless;
//按照从大到小的排列
quless.push(2);
quless.push(1);
quless.push(3);
cout << quless.top() << endl;
priority_queue<int, vector<int>, greater<int>> qugreater;
//按照从小到大的顺序排列
qugreater.push(2);
qugreater.push(1);
qugreater.push(3);
cout << qugreater.top() << endl;
5、关联式容器
(1)set
和Java中的set一样,set集合底层的实现是红黑树,不可以有重复的元素。
set<int> set = { 1,2,3,4 };
set.insert(5);
set.insert(1);
//删除元素
set.erase(1);
cout << "set集合中的元素" << set.size() << endl;
因为不能有重复的元素,所以在插入元素1的时候,就被替换了。
遍历set集合中的元素,需要使用迭代器,这也和Java中的一样。
//使用迭代器
vector<int>::iterator it = vc3.begin();
for (; it < vec.end(); it++)
{
cout << "使用Vector遍历" << *it << endl;
}
(2)map
和Java的map集合一样,用来保存键值对。
map<int, string> map1;
map1.insert({ 1, "A" });
//可以根据key来修改value
map1[1] = "D";
6、类型转换
(1)const_case
:修改类型的const
或者volatile
属性
const char* a;
char* b = const_cast<char*>(a);
将a
指针转换为b
指针;
(2)static_const
:
------->基础类型之间相互转换;float转换为int,int转为unsigned int
------->指针与void之间转换:float转换为void,Bean转换为void, 函数指针转换为void* ;
-------->子类指针/引用 和父类指针/引用之间转换
Parent* p = new Parent;
Child* c = static_cast<Child*>(p);
c->test();
通过static_cast
来将父类指针转换为子类指针。
(3)dynamic_cast
:动态转换
dynamic_cast
同样也是进行父类和子类之间的引用转换,dynamic_cast
和static_cast
之间的区别在于,dynamic_cast
会进行安全检查。
Parent* p = new Parent;
Child* c = dynamic_cast<Child*>(p);
c->test();
在使用dynamic_cast
进行类型转换的时候,父类中必须有一个虚函数。
在上述的代码中,实现这样的转换是会发生错误的,因为dynamic_cast
的安全机制,会出现空指针异常。
Parent* p = new Child;
Child* c = dynamic_cast<Child*>(p);
if (!c) {
cout << "转换失败" << endl;
}else {
c->test();
}
(4)reinterpret_cast
:获取指针的int地址
float f = 10;
float* p = &f;
int k = reinterpret_cast<int>(p);
cout << "指针的地址:" << k << endl;
7、文件
对于文件的操作,可以使用文件指针,来进行读写操作
//打开该路径下的文件
FILE* f1 = fopen("E:\\新建文件夹\\ndk\\example\\a.txt", "w");
//直接格式化写入数据
fprintf(f1, "kobe passed away");
//关闭文件流
fclose(f1);
当操作多媒体,像视频、图片的时候,需要使用fread()
、fwrite()
读取文件的时候,需要使用fscanf
来操作,但是fscanf
遇到空格就结束读取。
FILE* f3 = fopen("E:\\新建文件夹\\ndk\\example\\a.txt", "r");
char buffer[1025];
fscanf(f3, "%s", buffer);
cout << buffer << endl;
fclose(f3);
想要完整地读取,就使用fgets
来获取。
fgets(buffer, 1024, f3);
cout << buffer << endl;