C++ 进阶
标准库
vector
- 尾端可长
vector<T> arr = {};
vector<T> arr(n[,val])
.assign(b,e)(n,v)
.begin()
.end()
首/末位迭代器 类似指针.size()
.resize()
几个位置.capacity()
,reserve()
多少空间.back()
.front()
第一个 最后一个.push_back(val)
.pop_back()
删除/放到最后.empty()
是否为[].erase(b,e)
删除arr2.erase(arr2.begin());
可以删除首元素.insert(p,n,val)
插入.emplace(iter,v)
插入一个时可用arr1.swap(arr2)
交换at()
sort()
排序<algorithm>
unique()
去重reverse()
反转max/min_element(b,e)
最大小值- 遍历
for(auto i : arr){}
for(int i=0;i<arr.size();i++)
i = a.begin();while(i!=a.end())i++
- 截取
vector<int> arr2(arr1.begin() + 1, arr1.end() - 1);
arr2.assign(arr1.begin() + 1, arr1.end() - 1);
- 合并
arr1.insert(arr1.end(),arr2.begin(),arr2.end());
string
- 字符串
string s = "hello"
char*转stringstring s = to_string(num)
int转stringstring s(n,ch)
string s2(s1,b,e)
s+='c'
s.append('c')
s[2]
s.at(2)
.size()
.length
.find(sub)
找.empty()
.clear()
.insert()
.erase(p,n)
.substr(p,n)
子串.compare("hello")
比较.c_str()
转char*
map
unordered_map
map<T,T> m = { {k1,v1\},{k2,v2} }
.insert(pair<int, string>(k, v))
m[k] = v
.find(k)
没找到返回m.end()
.earse(k)
.earse(b,e)
.size()
.key_comp()
value_comp()
- 遍历
for(auto &&i : m)
.first()
.second()
deque
- 双端队列
deque<T> q
- 大部分api与vector类似
.push_front(v)
.pop_front()
.push_back(v)
.pop_back()
emplace_front(k)
.emplace_back(v)
在前后插入
list
stack
queue
set
cpp
void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c)
{
std::string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while(std::string::npos != pos2)
{
v.push_back(s.substr(pos1, pos2-pos1));
pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if(pos1 != s.length())
v.push_back(s.substr(pos1));
}
多进程
<unistd.h>
pid_t pid = fork();
if(pid==-1){fail}
if(pid==0){son process}
exit(0);
else{father process}
pid_t wait(int *status)
多线程
pthread.h
是c++98的用法,仅支持linux, c++11改用thread- 创建
<thread>
thread task(taskFunc,arg);
开启线程运行task.join()
运行完才往下走task.detach()
后台运行和主进程一块结束 (守护进程)
- this_threadd
get_id()
获取idyield()
放弃sleep_for(time)
暂停sleep_until()
等会儿执行
- 互斥量
- mutex 基本
- recursive_mutex 递归
- time_mutex 定时
- recursive_timed_mutex 定时递归
- lock 锁
- lock()
- unlock()
- trylock() 未上锁则锁住 已上锁返回true 同一个线程死锁
- lock_guard 对象
- unique_lock
- 原子操作 解决互斥锁速度慢的问题
#include <atomic>
atomic_int total(0);
total += 1;
正常使用
- condition_variable 条件变量
- condition_variable对象
- wait() 阻塞等通知
- wait_for() 等通知和超时
- wait_until() 等通知和时间点
- notify_one() 解锁一个
- notify_all() 通知解锁所有
- cv_status() 表示状态
- 线程池
- 在程序开始时创建多个线程,后面拿来用就行了,用完放回
- 信号量
<semaphore>
counting_semaphore sem(0);
初始值sem.acquire();
等待sem.release();
给出
- 死锁
- 任务一拿着锁1等锁2
- 任务二拿着锁2等锁1
cpp
#include <iostream>
#include <thread>
using namespace std;
void thread_1()
{
while (1)
{
cout << "子线程1111" << endl;
// this_thread::sleep_for(chrono::seconds(1));
}
}
void thread_2(int x)
{
while (1)
{
cout << "子线程2222" << endl;
// this_thread::sleep_for(chrono::seconds(2));
}
}
int main()
{
thread first(thread_1);
thread second(thread_2, 100);
first.detach();
second.detach();
first.join();
second.join();
for (int i = 0; i < 10; i++)
cout << "主线程\n";
return 0;
}
cpp
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int a = 0;
mutex mtx;
void print_block(int n, int c)
{
// mtx.lock();
// lock_guard<mutex> guard(mtx);
unique_lock<mutex> unique(mtx);
for (int i = 0; i < n; ++i)
{
a += c;
cout << a << ' ';
}
cout << '\n';
// mtx.unlock();
}
int main()
{
thread th1(print_block, 50, 1);
thread th2(print_block, 50, -1);
th1.join();
th2.join();
return 0;
}
cpp
#include <iostream>
#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
deque<int> q;
mutex mt;
condition_variable cond;
void thread_producer()
{
int count = 10;
while (count > 0)
{
unique_lock<mutex> unique(mt);
q.push_front(count);
unique.unlock();
cout << "producer a value: " << count << endl;
cond.notify_one();
this_thread::sleep_for(chrono::seconds(1));
count--;
}
}
void thread_consumer()
{
int data = 0;
while (data != 1)
{
unique_lock<mutex> unique(mt);
while (q.empty())
cond.wait(unique);
data = q.back();
q.pop_back();
cout << "consumer a value: " << data << endl;
unique.unlock();
}
}
int main()
{
thread t1(thread_consumer);
thread t2(thread_producer);
t1.join();
t2.join();
return 0;
}
cpp
#include <vector>
#include <queue>
#include <thread>
#include <iostream>
#include <condition_variable>
using namespace std;
const int MAX_THREADS = 1000; // 最大线程数目
template <typename T>
class threadPool
{
public:
threadPool(int number = 1);
~threadPool();
bool append(T *task);
// 工作线程需要运行的函数,不断的从任务队列中取出并执行
static void *worker(void *arg);
void run();
private:
// 工作线程
vector<thread> workThread;
// 任务队列
queue<T *> taskQueue;
mutex mt;
condition_variable condition;
bool stop;
};
template <typename T>
threadPool<T>::threadPool(int number) : stop(false)
{
if (number <= 0 || number > MAX_THREADS)
throw exception();
for (int i = 0; i < number; i++)
{
cout << "create thread:" << i << endl;
workThread.emplace_back(worker, this);
}
}
template <typename T>
inline threadPool<T>::~threadPool()
{
{
unique_lock<mutex> unique(mt);
stop = true;
}
condition.notify_all();
for (auto &wt : workThread)
wt.join();
}
template <typename T>
bool threadPool<T>::append(T *task)
{
// 往任务队列添加任务的时候,要加锁,因为这是线程池,肯定有很多线程
unique_lock<mutex> unique(mt);
taskQueue.push(task);
unique.unlock();
// 任务添加完之后,通知阻塞线程过来消费任务,有点像生产消费者模型
condition.notify_one();
return true;
}
template <typename T>
void *threadPool<T>::worker(void *arg)
{
threadPool *pool = (threadPool *)arg;
pool->run();
return pool;
}
template <typename T>
void threadPool<T>::run()
{
while (!stop)
{
unique_lock<mutex> unique(this->mt);
// 如果任务队列为空,就停下来等待唤醒,等待另一个线程发来的唤醒请求
while (this->taskQueue.empty())
this->condition.wait(unique);
T *task = this->taskQueue.front();
this->taskQueue.pop();
if (task)
task->process();
}
}
class Task
{
private:
int total = 0;
public:
void process();
};
// 任务具体实现什么功能,由这个函数实现
void Task::process()
{
// 这里就输出一个字符串
cout << "task successful " << endl;
this_thread::sleep_for(chrono::seconds(1));
}
int main(void)
{
threadPool<Task> pool(1);
while (1)
{
Task *task = new Task();
pool.append(task);
delete task;
}
}
cpp
#include <iostream>
#include <semaphore>
#include <thread>
using namespace std;
counting_semaphore sem(0);
void task1() // 线程函数 1 打印 a
{
sem.acquire();
cout << "task1\n" << endl;
}
void task2() // 线程函数 2 打印 l
{
cout << "task2\n" << endl;
this_thread::sleep_for(chrono::seconds(2));
sem.release();
}
int main() {
thread s1(task1);
thread s2(task2);
s1.join();
s2.join();
return 0;
}
cpp
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex mt1;
mutex mt2;
void thread1() {
cout << "thread1 begin" << endl;
lock_guard<mutex> guard1(mt1);
this_thread::sleep_for(chrono::seconds(1));
lock_guard<mutex> guard2(mt2);
cout << "hello thread1" << endl;
}
void thread2() {
cout << "thread2 begin" << endl;
lock_guard<mutex> guard1(mt2);
this_thread::sleep_for(chrono::seconds(1));
lock_guard<mutex> guard2(mt1);
cout << "hello thread2" << endl;
}
int main() {
thread t1(thread1);
thread t2(thread2);
t1.join();
t2.join();
cout << "thread end" << endl;
return 0;
}
Socket
- server
socket()
bind()
listen()
accept()
read()
recv()
write()
send()
close()
- client
socket()
connect()
read()
recv()
write()
send()
close()
聊天室
cpp
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <map>
#include <mutex>
#include <thread>
using namespace std;
int cnt = 0;
mutex mtx;
map<string, int> clients;
void sendMsg(string msg) {
for (auto i : clients) send(i.second, msg.c_str(), msg.length(), 0);
}
void online(int client) {
char msg[100] = {0};
while (recv(client, msg, 100, 0) > 0) {
cout << msg << endl;
if (msg[0] == '@') {
if (clients.find(msg) == clients.end()) {
clients[msg] = client;
sendMsg(msg);
} else {
cout << "already in" << endl;
mtx.lock();
cnt--;
mtx.unlock();
close(client);
// return;
}
} else
sendMsg(msg);
}
// 连接断开
cout << "断开" << endl;
mtx.lock();
for (auto i : clients) {
if (i.second == client) {
cout << i.first << "leave" << endl;
clients.erase(i.first);
break;
}
}
cnt--;
mtx.unlock();
close(client);
return;
}
int main() {
struct sockaddr_in serverAddr, clientAddr;
unsigned int temp = sizeof(clientAddr);
// pid
int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int client;
serverAddr.sin_family = AF_INET; // ipv4
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // ip
serverAddr.sin_port = htons(8080); // 端口
bind(server, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
listen(server, 99);
while (1) {
client = accept(server, (struct sockaddr *)&clientAddr, &temp);
mtx.lock();
cnt++;
mtx.unlock();
thread th(online, client);
th.detach();
cout << "new connection" << endl;
}
close(server);
return 0;
}
cpp
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <map>
#include <mutex>
#include <thread>
using namespace std;
string name;
void send_msg(int sock) {
string msg;
while (1) {
cin >> msg;
if (msg == "quit") {
close(sock);
exit(0);
}
string name_msg = name + ": " + msg;
send(sock, name_msg.c_str(), name_msg.length() + 1, 0);
}
}
void recv_msg(int sock) {
while (1) {
char name_msg[100] = {0};
int str_len = recv(sock, name_msg, 100, 0);
if (str_len < 1) {
exit(-1);
}
cout << string(name_msg) << endl;
}
}
int main() {
cout << "name:";
cin >> name;
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serverAddr.sin_port = htons(8080);
int pid = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(pid, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
string temp = "@" + name;
send(pid, temp.c_str(), temp.length(), 0);
std::thread snd(send_msg, pid);
std::thread rcv(recv_msg, pid);
snd.join();
rcv.join();
close(pid);
return 0;
}