STL容器相關(guān)
一、vector向量
// Java的集合框架 非常強(qiáng)大 相當(dāng)于 C++ STL(標(biāo)準(zhǔn)模板庫(kù)) #include <iostream>
// TODO STL 是“Standard Template Library”的縮寫,中文譯為“標(biāo)準(zhǔn)模板庫(kù)”。STL 是 C++ 標(biāo)準(zhǔn)庫(kù)的一部分,不用單獨(dú)安裝。
// STL 有很多很多的容器
// C ++ vector 向量 容器 (內(nèi)部:封裝動(dòng)態(tài)大小數(shù)組作為容器,能夠存放任意的動(dòng)態(tài)數(shù)組【數(shù)據(jù)結(jié)構(gòu)】)
#include <iostream>
#include <vector> // 引入 vector 容器的支持
using namespace std;
int main() {
vector<int> vector1;
vector<int> vector2(10); // 指定10的空間大小
vector<int> vector3(10, 0); // 有了10個(gè)值了 每個(gè)值都是0
vector<int> vector4;
// vector4.begin() 迭代器 插入到前面
// vector4.end() 迭代器 插入到后面
// 插入數(shù)據(jù)
vector4.insert(vector4.begin(), 40);
vector4.insert(vector4.begin(), 60);
vector4.insert(vector4.begin(), 80);
vector4.insert(vector4.begin(), 100);
vector4.insert(vector4.begin(), 200);
// 第一個(gè) 200 100 80 60 40
cout << " 修改前:vector4.front():" << vector4.front() << endl;
vector4.front() = 99; // 默認(rèn)修改第一個(gè)
cout << " 修改后:vector4.front():" << vector4.front() << endl;
// 最后一個(gè)
cout << " 修改前:vector4.back():" << vector4.back() << endl;
vector4.back() = 777; // 默認(rèn)修改最后 99 100 80 60 777
cout << " 修改后:vector4.back():" << vector4.back() << endl;
vector4.erase(vector4.begin()); // 移除第一個(gè)元素(內(nèi)部:通過(guò)迭代器的位置 進(jìn)行移除) 刪除 100 80 60 777
// 循環(huán)打印,默認(rèn) 從大到小輸出
for (int i = 0; i < vector4.size(); ++i) {
cout << "item:" << vector4[i] << endl; //100 80 60 777
}
// KT的類型推到 相當(dāng)于 C++ auto
/*var a = 10;
var b = 30.4f;
var c = "";*/
// 迭代器 循環(huán)遍歷
// auto Kotlin自帶類型推導(dǎo)
// for (vector<int>::iterator iteratorVar = vector4.begin(); iteratorVar != vector4.end(); iteratorVar++) {
for (auto iteratorVar = vector4.begin(); iteratorVar != vector4.end(); iteratorVar++) {
// 迭代器 當(dāng)中指針操作 iteratorVar++
cout << "迭代器:" << *iteratorVar << endl;
}
return 0;
}
二、stack棧
// 先進(jìn)后出
#include <iostream>
#include <stack>
using namespace std;
// NDK開(kāi)發(fā)者 幾乎用不到
int main() {
stack<int> stackVar;
// 壓棧(注意:stack無(wú)法指定那個(gè)位置去壓棧)
stackVar.push(30);
stackVar.push(60);
stackVar.push(90);
//90 60 30
// [] 角標(biāo)是不行的,內(nèi)部沒(méi)有重載此運(yùn)算符
/*for (int i = 0; i < stackVar.size(); ++i) {
// cout << stackVar[i] << endl;
// cout << stackVar.at() << endl;
}*/
// 他根本就沒(méi)有迭代器
// 開(kāi)發(fā)者 自己組裝 迭代器 遍歷
/*for (stack<int>::iterator; i < ; ++i) {
}*/
// 慎用,為什么? 元素被彈完了
// 這種方式是可以的,手槍把子彈全部打完【會(huì)把元素清空】
while (!stackVar.empty()) {
int top = stackVar.top(); // top == 獲取棧頂?shù)脑? cout << "獲取棧頂?shù)脑兀? << top << endl; // 永遠(yuǎn)拿 90
stackVar.pop(); // 把棧頂?shù)脑?彈出去 【刪除】
}
/*int top = stackVar.top();
cout << top << endl;*/
return 0;
}
三、隊(duì)列queue
//先進(jìn)先出
#include <iostream>
#include <queue> // 隊(duì)列支持(內(nèi)部:基本上 鏈表 、 數(shù)組 )
using namespace std;
int main() {
queue<int> queueVar;
queueVar.push(20);
queueVar.push(40);
queueVar.push(60);
//20 40 60
// 第一個(gè)元素是誰(shuí) 20 FIFO 原則
cout << " 修改前: queueVar.front():" << queueVar.front() << endl;
queueVar.front() = 88; //88 40 60
cout << " 修改后: queueVar.front():" << queueVar.front() << endl;
// 最后一個(gè)
cout << " 修改前: queueVar.back():" << queueVar.back() << endl;
queueVar.back() = 88; // 88 40 88
cout << " 修改后: queueVar.back():" << queueVar.back() << endl;
// 沒(méi)有找到 角標(biāo)
/*for (int i = 0; i < 9; ++i) {
queueVar[i];
}*/
// 他根本就沒(méi)有迭代器
/*for (queue<int>::iterator; i < ; ++i) {
}*/
// 慎用,為什么? 前面的元素全部被消費(fèi)完了
while (!queueVar.empty()) {
cout << "while1:" << queueVar.front() << endl;
queueVar.pop(); // 把前面的元素 給消費(fèi)掉 【刪除】
}
return 0;
}
四、list
/ / Java:ArrayList采用Object[]數(shù)組, C++的list 內(nèi)部:采用鏈表
#include <iostream>
#include <list> // list容器的支持
using namespace std;
int main() {
list<int> listVar;
// 插入操作
listVar.push_front(50); // 插入到前面 明確
listVar.push_back(60); // 插入到后面
listVar.insert(listVar.begin(), 70); // 插入到前面 靈活
listVar.insert(listVar.end(), 80); // 插入到后面
//70 50 60 80
// 修改操作
listVar.back() = 88;
listVar.front() = 55;
// 刪除
listVar.erase(listVar.begin()); // 刪除最前面的 55
listVar.erase(listVar.end()); // 刪除最后面的 88
// list 迭代器
// 不用通過(guò)角標(biāo)去訪問(wèn),也不能修改 遍歷
for (list<int>::iterator it = listVar.begin(); it != listVar.end() ; it ++) {
cout << *it << endl;
}
return 0;
}
五、set
// set(內(nèi)部:紅黑樹(shù)結(jié)構(gòu)),會(huì)對(duì)你存入的數(shù)據(jù)進(jìn)行排序,但是絕對(duì)不允許元素相同
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int, less<int>> setVar; // __x < __y 從小到大,默認(rèn)情況下 就是 less
// 添加參數(shù),不需要用迭代器,也不需要指定位置
setVar.insert(1);
setVar.insert(3);
setVar.insert(2);
setVar.insert(4);
// 重復(fù)插入,并不會(huì)報(bào)錯(cuò) std::pair<iterator, bool>
pair<set<int, less<int>>::iterator, bool> res = setVar.insert(8);
// res.first 獲取第一個(gè)元素 迭代器 當(dāng)前迭代器 最后一個(gè)位置
// res.second 獲取第二個(gè)元素 bool
bool insert_success = res.second;
if (insert_success) {
cout << "恭喜你,插入成功" << endl;
} else {
cout << "哎,插入失敗.." << endl;
}
// 全部遍歷 auto 自動(dòng)推到
for (auto it = setVar.begin(); it != setVar.end() ; it ++) {
cout << *it << endl;
}
return 0;
}
六、謂詞
// 謂詞 設(shè)計(jì)對(duì)象的排序
#include <iostream>
#include <set>
using namespace std;
class Person {
public:
string name;
int id;
Person(string name, int id) : name(name), id(id) {}
};
// C++ 都是一些常規(guī)的 謂詞 不能滿足功能, 模仿C++源碼的謂詞 自定義謂詞 解決這個(gè)問(wèn)題
// C++締造者寫的這個(gè)源碼 沒(méi)有對(duì)象比較的功能 【系統(tǒng)源碼謂詞 做不到對(duì)象比較功能】
// bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; }
// 我們就自定義這個(gè)功能 【自定義謂詞 沒(méi)有達(dá)到謂詞的標(biāo)準(zhǔn)】
bool doCompareAction(const Person& person1, const Person& person2) {
return person1.id < person2.id;
};
// 真正的謂詞
struct doCompareAction2 {
public:
bool operator() (const Person& __x, const Person& __y) {
return __x.id < __y.id;
}
};
struct doCompareAction3 {
public:
bool operator() (const Person& __x, const Person& __y) {
return __x.id > __y.id;
}
};
int main() {
// 默認(rèn)是 less return 對(duì)象1 < 對(duì)象2;
set<Person, doCompareAction2> setVar;
// set<Person, doCompareAction3> setVar;
// 構(gòu)建對(duì)象
Person p1 ("Snake", 1);
Person p2 ("kevin", 2);
Person p3 ("Derry", 3);
// 把構(gòu)建的對(duì)象 插入到 set 容器里面去
setVar.insert(p1);
setVar.insert(p2);
setVar.insert(p3);
// name string --- c_str() ----> char *
for (set<Person>::iterator it = setVar.begin(); it != setVar.end() ; it ++) {
cout << it->name.c_str() << " , " << it->id << endl;
}
return 0;
}
七、線程
1、基礎(chǔ)
#include <iostream>
#include <pthread.h>
using namespace std;
// void *(*)(void *)
void * customPthreadTask(void * pVoid) { // 異步線程 相當(dāng)于Java的Thread.run函數(shù)一樣
// C++轉(zhuǎn)換static_cast 轉(zhuǎn)換指針操作的
int * number = static_cast<int *>(pVoid); // pVoid==number int的地址,所以我用int*接收,很合理
cout << "異步線程執(zhí)行了:" << *number << endl;
return 0; // 必須返回
}
int main() {
int number = 9527;
/**
int pthread_create (pthread_t *, // 參數(shù)一:線程ID
const pthread_attr_t *, // 參數(shù)二:線程屬性
void *(*)(void *), // 參數(shù)三:函數(shù)指針的規(guī)則
void *); // 參數(shù)四:給函數(shù)指針傳遞的內(nèi)容,void * 可以傳遞任何內(nèi)容
*/
pthread_t pthreadID; // 線程ID,每個(gè)線程都需要有的線程ID
pthread_create(&pthreadID, 0, customPthreadTask, &number);
return 0;
}
2、pthread的3種情況
// 第一種情況,main函數(shù)只要結(jié)束,不等異步線程,全部結(jié)束
// 第二種情況,我們開(kāi)發(fā)者,千萬(wàn)不要讓 main函數(shù)睡眠的方式,去等待異步線程
// 第三種情況,main函數(shù)一直等待 異步線程,只有異步線程執(zhí)行完成后,我在執(zhí)行 join后面的代碼
#include <iostream>
#include <pthread.h> // Derry Cygwin 有 pthreads支持
#include <unistd.h>
using namespace std;
// void *(*)(void *)
void * runTask(void * pVoid) { // 異步線程 子線程
int number = *static_cast<int *>(pVoid);
cout << "異步線程執(zhí)行了:" << number << endl;
for (int i = 0; i < 10; ++i) {
cout << "run:" << i << endl;
sleep(1);
}
return 0;
}
int main() {
int number = 999;
pthread_t pthreadID;
pthread_create(&pthreadID, 0, runTask, &number);
// 為了演示第二種情況
// sleep(3); // main函數(shù)只 異步線程三秒鐘
// 異步線程在執(zhí)行的過(guò)程中,我們的main函數(shù) 相當(dāng)于 阻塞在這里不動(dòng)了,只有異步線程執(zhí)行完成后,我才開(kāi)始執(zhí)行join后面的代碼
pthread_join(pthreadID, 0);
cout << "main函數(shù)即將彈棧..." << endl;
return 0;
}
3、鎖
// C++ 互斥鎖 == Java版本(synchronize) 多線程操作的安全 持有內(nèi)置鎖
#include <iostream>
#include <pthread.h>
#include <queue>
#include <unistd.h> // sleep(秒)
using namespace std;
queue<int> queueData; // 定義一個(gè)全局的隊(duì)列,用于 存儲(chǔ)/獲取
pthread_mutex_t mutex; // 定義一個(gè)互斥鎖
// void *(*)(void *)
void * task(void * pVoid) {
/*synchronize(鎖) {
// code
}*/
pthread_mutex_lock(&mutex); // 鎖住
cout << "異步線程-當(dāng)前線程的標(biāo)記是:" << *static_cast<int *>(pVoid) << "異步線程" << endl;
if (!queueData.empty()) { // 有元素
printf("異步線程-獲取隊(duì)列的數(shù)據(jù):%d\n", queueData.front());
queueData.pop(); // 把數(shù)據(jù)彈出去,刪除的意思
} else { // 沒(méi)有元素
printf("異步線程-隊(duì)列中沒(méi)有數(shù)據(jù)了\n");
}
// sleep(0.2);
pthread_mutex_unlock(&mutex); // 解鎖
return 0;
}
int main()
{
// 初始化 互斥鎖
pthread_mutex_init(&mutex, NULL);
// 給隊(duì)列 初始化數(shù)據(jù) 手動(dòng)增加數(shù)據(jù)進(jìn)去
for (int i = 10001; i < 10011; ++i) {
queueData.push(i);
}
// 一次性定義10個(gè)線程
pthread_t pthreadIDArray[10];
for (int i = 0; i < 10; ++i) {
pthread_create(&pthreadIDArray[i], 0, task, &i);
// 不能使用 join,如果使用(就變成順序的方式,就沒(méi)有多線程的意義了,所以不能寫join)
// pthread_join(pthreadIDArray[i], 0);
}
// main函數(shù)等 異步線程
sleep(12);
// 銷毀 互斥鎖
pthread_mutex_destroy(&mutex);
cout << "main函數(shù)即將彈棧..." << endl;
// 每次運(yùn)行 效果都不同:1,8,9,10,3,2,5,8
// 每次運(yùn)行 效果都是錯(cuò)亂
return 0;
}