前言
本系列内容为程序媛学习C++时做的笔记。以代码为主,并备注了打印结果以及详尽的解释注释。希望对你有所帮助。
引用关系修改右值
#include <iostream>
using namespace std;
class Person {
string name = "zhang";//旧变量
public:
string getName() {
//getName函数的name 与 main函数世界得到的name 是新旧两个变量而已,他们是值传递,所以右值修改时,影响不了里面的旧变量
return name;
}
string &getName2() {
//这里是引用关系,两个name是一块内存空间 有多个别名而已,所以右值修改时,直接影响旧变量
return name;
}
};
int main() {
Person p;
//左值获取:string name = p.getName();
//右值修改:p.getName() = "张三";
p.getName() = "张三";//修改失败
cout << p.getName() << endl;//zhang
p.getName2() = "李四";//修改成功
cout << p.getName2() << endl;//李四
return 0;
}
多线程
多线程的使用
pthread_create:创建线程
#include <iostream>
#include <pthread.h> //Cygwin 有 pthreads支持
#include <unistd.h>
using namespace std;
// void *(*)(void *)
void * runTask(void * pVoid) { // 异步线程 子线程
int number = *static_cast<int *>(pVoid);
cout << "异步线程执行了:" << 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);
// 异步线程在执行的过程中,我们的main函数 相当于 阻塞在这里不动了,只有异步线程执行完成后,我才开始执行join后面的代码
pthread_join(pthreadID, 0);
cout << "main函数即将弹栈..." << endl;
return 0;
}
打印:
条件变量+互斥锁
== Java版本的(notify 与 wait 操作)
[ˈmjuːtex] 互斥
pthread_mutex_t mutex:定义一个互斥锁
pthread_mutex_init(&mutex, NULL):初始化互斥锁
pthread_mutex_destroy(&mutex):销毁互斥锁
pthread_mutex_lock(&mutex):加锁
pthread_mutex_unlock(&mutex):解锁
实现效果:
代码示例:
T7
#pragma once
#include <iostream>
#include "safe_queue_too.h"
using namespace std;
SafeQueueClass<int> sq;
// 模拟演示 消费者 相当于java的runnable
void * getMethod(void *) {
while (true) {
printf("getMethod\n");
int value;
sq.get(value);
printf("消费者get 得到的数据:%d\n", value);
// 你只要传入 -1 就结束当前循环
if (-1 == value) {
printf("消费者get 全部执行完毕\n");
break;
}
}
return 0;//必须有返回值,否则有奇怪的报错
}
// 模拟演示 生产者
void * setMethod(void *) {
while (true) {
printf("setMethod\n");
int value;
printf("请输入你要生成的信息:\n");
cin >> value;
// 你只要传入 -1 就结束当前循环
if (-1 == value) {
sq.add(value); // 为了让消费者 可以结束循环
break;
}
sq.add(value);
}
return 0;
}
int main() {
pthread_t pthreadGet;
pthread_create(&pthreadGet, 0, getMethod, 0);
// pthread_join(pthreadGet, 0); 不能写在这,否则,下面的代码,可能无法有机会执行
pthread_t pthreadSet;
pthread_create(&pthreadSet, 0, setMethod, 0);
pthread_join(pthreadGet, 0);
pthread_join(pthreadSet, 0);
return 0;
}
safe_queue_too.h
// 生产者 消费者 工具类 播放器 有用
#ifndef CPPCLIONPROJECT_SAFE_QUEUE_TOO_H
#define CPPCLIONPROJECT_SAFE_QUEUE_TOO_H
#endif //CPPCLIONPROJECT_SAFE_QUEUE_TOO_H
#pragma once // 防止重复写 include 的控制
#include <iostream>
#include <string>
#include <pthread.h>
#include <string>
#include <queue>
using namespace std;
// 定义模版函数 int double float == Java的泛型
template<typename T>
class SafeQueueClass {
private:
queue<T> queue; // 定义队列
pthread_mutex_t mutex; // 定义互斥锁(不允许有野指针)
pthread_cond_t cond; // 条件变量,为了实现 等待 读取 等功能 (不允许有野指针)
public:
SafeQueueClass() {
// 初始化 互斥锁
pthread_mutex_init(&mutex, 0);
// 初始化 条件变量
pthread_cond_init(&cond, 0);
}
~SafeQueueClass() {
// 回收 互斥锁
pthread_mutex_destroy(&mutex);
// 回收 条件变量
pthread_cond_destroy(&cond);
}
// 加入到队列中(进行生成)
void add(T t) {
// 为了安全 加锁
pthread_mutex_lock(&mutex);
queue.push(t); // 把数据加入到队列中
// 告诉消费者,我已经生产好了
// pthread_cond_signal(&cond) // Java notify 单个的
pthread_cond_broadcast(&cond); // Java notifyAll 所有的
cout << "add queue.push 我已经notifyAll所有等待线程了" << endl;
// 解锁
pthread_mutex_unlock(&mutex);
}
// 从队列中获取(进行消费) 外面的人消费 你可以直接返回,你也可以采用引用
void get(T & t) {
// 为了安全 加锁
pthread_mutex_lock(&mutex);
while (queue.empty()) {
cout << "get empty 我已经乖乖等待中.." << endl;
pthread_cond_wait(&cond, &mutex); // 相当于 Java的 wait 等待了[有可能被系统唤醒]
}
// 证明被唤醒了
t = queue.front(); // 得到 队列中的元素数据 仅此而已
queue.pop(); // 删除元素
// 解锁
pthread_mutex_unlock(&mutex);
}
};
打印结果: