C++实现生产者和消费者模型

2023-05-16

C++实现生产者和消费者模型

  • C++实现生产者和消费者模型
    • 1、实现细节
    • 2、单生产者-单消费者模型
    • 3、单生产者-多消费者模型
    • 4、多生产者-单消费者模型
    • 5、多生产者-多消费者模型
  • 参考

C++实现生产者和消费者模型

1、实现细节

  • 具体的实现逻辑是构建一个queue来存储生产的数据,queue不满时可以生产,不空时可以消费。
  • 对于这个队列,采用阻塞队列的实现思路。
  • 先实现构造函数,初始化一个unique_lock供condition_variable使用。
    • 如何在类里面使用unique_lock等需要初始化,并且初始化会加锁的对象。这要研究下。我的理解是构造列表初始化,然后函数体里unlock。
    • 对于条件变量,申请两个,分别控制consumer和producer。
  • 然后就是入和出队列的细节。
    • 首先加锁。
    • 循环判断一下目前的队列情况,对于各自的特殊情况(队满和队空)进行处理。
    • 唤醒一个线程来处理特殊情况。
    • 等待处理完毕。
    • 处理入和出队列操作。
    • 最后释放锁。

2、单生产者-单消费者模型

  • 单生产者-单消费者模型中只有一个生产者和一个消费者,
  • 生产者不停地往产品库中放入产品,
  • 消费者则从产品库中取走产品,
  • 产品库容积有限制,只能容纳一定数目的产品,
  • 如果生产者生产产品的速度过快,则需要等待消费者取走产品之后,产品库不为空才能继续往产品库中放置新的产品,
  • 相反,如果消费者取走产品的速度过快,则可能面临产品库中没有产品可使用的情况,此时需要等待生产者放入一个产品后,消费者才能继续工作。

C++11实现单生产者单消费者模型的代码如下:

#include <unistd.h>

#include <cstdlib>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

static const int bufSize = 10; // Item buffer size.
static const int ProNum = 20;   // How many items we plan to produce.

struct resource {
	int buf[bufSize]; // 产品缓冲区, 配合 read_pos 和 write_pos 模型环形队列.
	size_t read_pos; // 消费者读取产品位置.
	size_t write_pos; // 生产者写入产品位置.
	std::mutex mtx; // 互斥量,保护产品缓冲区
	std::condition_variable not_full; // 条件变量, 指示产品缓冲区不为满.
	std::condition_variable not_empty; // 条件变量, 指示产品缓冲区不为空.
} instance; // 产品库全局变量, 生产者和消费者操作该变量.

typedef struct resource resource;


void Producer(resource *ir, int item)
{
	std::unique_lock<std::mutex> lock(ir->mtx);
	while (((ir->write_pos + 1) % bufSize)
		== ir->read_pos) { // item buffer is full, just wait here.
		std::cout << "Producer is waiting for an empty slot...\n";
		(ir->not_full).wait(lock); // 生产者等待"产品库缓冲区不为满"这一条件发生.
	}

	(ir->buf)[ir->write_pos] = item; // 写入产品.
	(ir->write_pos)++; // 写入位置后移.

	if (ir->write_pos == bufSize) // 写入位置若是在队列最后则重新设置为初始位置.
		ir->write_pos = 0;

	(ir->not_empty).notify_all(); // 通知消费者产品库不为空.
}

int Consumer(resource *ir)
{
	int data;
	std::unique_lock<std::mutex> lock(ir->mtx);
	// item buffer is empty, just wait here.
	while (ir->write_pos == ir->read_pos) {
		std::cout << "Consumer is waiting for items...\n";
		(ir->not_empty).wait(lock); // 消费者等待"产品库缓冲区不为空"这一条件发生.
	}

	data = (ir->buf)[ir->read_pos]; // 读取某一产品
	(ir->read_pos)++; // 读取位置后移

	if (ir->read_pos >= bufSize) // 读取位置若移到最后,则重新置位.
		ir->read_pos = 0;

	(ir->not_full).notify_all(); // 通知消费者产品库不为满.

	return data; // 返回产品.
}


void ProducerTask() // 生产者任务
{
	for (int i = 1; i <= ProNum; ++i) {
		// sleep(1);
		std::cout << "Produce the " << i << "^th item..." << std::endl;
		Producer(&instance, i); // 循环生产 ProNum 个产品.
	}
}

void ConsumerTask() // 消费者任务
{
	static int cnt = 0;
	while (1) {
		sleep(1);
		int item = Consumer(&instance); // 消费一个产品.
		std::cout << "Consume the " << item << "^th item" << std::endl;
		if (++cnt == ProNum) break; // 如果产品消费个数为 ProNum, 则退出.
	}
}

void Initresource(resource *ir)
{
	ir->write_pos = 0; // 初始化产品写入位置.
	ir->read_pos = 0; // 初始化产品读取位置.
}

int main()
{
	Initresource(&instance);
	std::thread producer(ProducerTask); // 创建生产者线程.
	std::thread consumer(ConsumerTask); // 创建消费之线程.
	producer.join();
	consumer.join();
}

在这里插入图片描述

3、单生产者-多消费者模型

与单生产者和单消费者模型不同的是,单生产者-多消费者模型中可以允许多个消费者同时从产品库中取走产品。所以除了保护产品库在多个读写线程下互斥之外,还需要维护消费者取走产品的计数器,代码如下:

#include <unistd.h>

#include <cstdlib>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

static const int bufSize = 8; // Item buffer size.
static const int ProNum = 30;   // How many items we plan to produce.

struct resource {
	int buf[bufSize]; // 产品缓冲区, 配合 read_pos 和 write_pos 模型环形队列.
	size_t read_pos; // 消费者读取产品位置.
	size_t write_pos; // 生产者写入产品位置.
	size_t item_counter;
	std::mutex mtx; // 互斥量,保护产品缓冲区
	std::mutex item_counter_mtx;
	std::condition_variable not_full; // 条件变量, 指示产品缓冲区不为满.
	std::condition_variable not_empty; // 条件变量, 指示产品缓冲区不为空.
} instance; // 产品库全局变量, 生产者和消费者操作该变量.

typedef struct resource resource;


void Producer(resource *ir, int item)
{
	std::unique_lock<std::mutex> lock(ir->mtx);
	while (((ir->write_pos + 1) % bufSize)
		== ir->read_pos) { // item buffer is full, just wait here.
		std::cout << "Producer is waiting for an empty slot...\n";
		(ir->not_full).wait(lock); // 生产者等待"产品库缓冲区不为满"这一条件发生.
	}

	(ir->buf)[ir->write_pos] = item; // 写入产品.
	(ir->write_pos)++; // 写入位置后移.

	if (ir->write_pos == bufSize) // 写入位置若是在队列最后则重新设置为初始位置.
		ir->write_pos = 0;

	(ir->not_empty).notify_all(); // 通知消费者产品库不为空.
	lock.unlock(); // 解锁.
}

int Consumer(resource *ir)
{
	int data;
	std::unique_lock<std::mutex> lock(ir->mtx);
	// item buffer is empty, just wait here.
	while (ir->write_pos == ir->read_pos) {
		std::cout << "Consumer is waiting for items...\n";
		(ir->not_empty).wait(lock); // 消费者等待"产品库缓冲区不为空"这一条件发生.
	}

	data = (ir->buf)[ir->read_pos]; // 读取某一产品
	(ir->read_pos)++; // 读取位置后移

	if (ir->read_pos >= bufSize) // 读取位置若移到最后,则重新置位.
		ir->read_pos = 0;

	(ir->not_full).notify_all(); // 通知消费者产品库不为满.
	lock.unlock(); // 解锁.

	return data; // 返回产品.
}


void ProducerTask() // 生产者任务
{
	for (int i = 1; i <= ProNum; ++i) {
		// sleep(1);
		std::cout << "Producer thread " << std::this_thread::get_id()
			<< " producing the " << i << "^th item..." << std::endl;
		Producer(&instance, i); // 循环生产 ProNum 个产品.
	}
	std::cout << "Producer thread " << std::this_thread::get_id()
		<< " is exiting..." << std::endl;
}

void ConsumerTask() // 消费者任务
{
	bool ready_to_exit = false;
	while (1) {
		sleep(1);
		std::unique_lock<std::mutex> lock(instance.item_counter_mtx);
		if (instance.item_counter < ProNum) {
			int item = Consumer(&instance);
			++(instance.item_counter);
			std::cout << "Consumer thread " << std::this_thread::get_id()
				<< " is consuming the " << item << "^th item" << std::endl;
		}
		else
			ready_to_exit = true;
		if (ready_to_exit == true)
			break;
	}
	std::cout << "Consumer thread " << std::this_thread::get_id()
		<< " is exiting..." << std::endl;
}

void Initresource(resource *ir)
{
	ir->write_pos = 0; // 初始化产品写入位置.
	ir->read_pos = 0; // 初始化产品读取位置.
	ir->item_counter = 0;
}

int main()
{
	Initresource(&instance);
	std::thread producer(ProducerTask);
	std::thread consumer1(ConsumerTask);
	std::thread consumer2(ConsumerTask);
	std::thread consumer3(ConsumerTask);
	std::thread consumer4(ConsumerTask);

	producer.join();
	consumer1.join();
	consumer2.join();
	consumer3.join();
	consumer4.join();
}

在这里插入图片描述

4、多生产者-单消费者模型

与单生产者和单消费者模型不同的是,多生产者-单消费者模型中可以允许多个生产者同时向产品库中放入产品。所以除了保护产品库在多个读写线程下互斥之外,还需要维护生产者放入产品的计数器,代码如下:

#include <unistd.h>

#include <cstdlib>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

static const int bufSize = 8; // Item buffer size.
static const int ProNum = 20;   // How many items we plan to produce.

struct resource {
	int buf[bufSize]; // 产品缓冲区, 配合 read_pos 和 write_pos 模型环形队列.
	size_t read_pos; // 消费者读取产品位置.
	size_t write_pos; // 生产者写入产品位置.
	size_t item_counter;
	std::mutex mtx; // 互斥量,保护产品缓冲区
	std::mutex item_counter_mtx;
	std::condition_variable not_full; // 条件变量, 指示产品缓冲区不为满.
	std::condition_variable not_empty; // 条件变量, 指示产品缓冲区不为空.
} instance; // 产品库全局变量, 生产者和消费者操作该变量.

typedef struct resource resource;


void Producer(resource *ir, int item)
{
	std::unique_lock<std::mutex> lock(ir->mtx);
	while (((ir->write_pos + 1) % bufSize)
		== ir->read_pos) { // item buffer is full, just wait here.
		std::cout << "Producer is waiting for an empty slot...\n";
		(ir->not_full).wait(lock); // 生产者等待"产品库缓冲区不为满"这一条件发生.
	}

	(ir->buf)[ir->write_pos] = item; // 写入产品.
	(ir->write_pos)++; // 写入位置后移.

	if (ir->write_pos == bufSize) // 写入位置若是在队列最后则重新设置为初始位置.
		ir->write_pos = 0;

	(ir->not_empty).notify_all(); // 通知消费者产品库不为空.
}

int Consumer(resource *ir)
{
	int data;
	std::unique_lock<std::mutex> lock(ir->mtx);
	// item buffer is empty, just wait here.
	while (ir->write_pos == ir->read_pos) {
		std::cout << "Consumer is waiting for items...\n";
		(ir->not_empty).wait(lock); // 消费者等待"产品库缓冲区不为空"这一条件发生.
	}

	data = (ir->buf)[ir->read_pos]; // 读取某一产品
	(ir->read_pos)++; // 读取位置后移

	if (ir->read_pos >= bufSize) // 读取位置若移到最后,则重新置位.
		ir->read_pos = 0;

	(ir->not_full).notify_all(); // 通知消费者产品库不为满.

	return data; // 返回产品.
}


void ProducerTask() // 生产者任务
{
	bool ready_to_exit = false;
	while (1) {
		sleep(1);
		std::unique_lock<std::mutex> lock(instance.item_counter_mtx);
		if (instance.item_counter < ProNum) {
			++(instance.item_counter);
			Producer(&instance, instance.item_counter);
			std::cout << "Producer thread " << std::this_thread::get_id()
				<< " is producing the " << instance.item_counter
				<< "^th item" << std::endl;
		}
		else 
			ready_to_exit = true;
		if (ready_to_exit == true) 
			break;
	}
	std::cout << "Producer thread " << std::this_thread::get_id()
		<< " is exiting..." << std::endl;
}

void ConsumerTask() // 消费者任务
{
	static int cnt = 0;
	while (1) {
		sleep(1);
		cnt++;
		if (cnt <= ProNum)
		{
			int item = Consumer(&instance); // 消费一个产品.
			std::cout << "Consumer thread " << std::this_thread::get_id()
				<< " is consuming the " << item << "^th item" << std::endl;
		}
		
		else
			break; // 如果产品消费个数为 ProNum, 则退出.
	}
	std::cout << "Consumer thread " << std::this_thread::get_id()
		<< " is exiting..." << std::endl;
}

void Initresource(resource *ir)
{
	ir->write_pos = 0; // 初始化产品写入位置.
	ir->read_pos = 0; // 初始化产品读取位置.
	ir->item_counter = 0;
}

int main()
{
	Initresource(&instance);
	std::thread producer1(ProducerTask);
	std::thread producer2(ProducerTask);
	std::thread producer3(ProducerTask);
	std::thread producer4(ProducerTask);
	std::thread consumer(ConsumerTask);

	producer1.join();
	producer2.join();
	producer3.join();
	producer4.join();
	consumer.join();
}

在这里插入图片描述

5、多生产者-多消费者模型

该模型可以说是前面两种模型的综合,程序需要维护两个计数器,分别是生产者已生产产品的数目和消费者已取走产品的数目。另外也需要保护产品库在多个生产者和多个消费者互斥地访问。

#include <unistd.h>

#include <cstdlib>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

static const int bufSize = 8; // Item buffer size.
static const int ProNum = 20;   // How many items we plan to produce.

struct resource {
	int buf[bufSize]; // 产品缓冲区, 配合 read_pos 和 write_pos 模型环形队列.
	size_t read_pos; // 消费者读取产品位置.
	size_t write_pos; // 生产者写入产品位置.
	size_t pro_item_counter;
	size_t con_item_counter;
	std::mutex mtx; // 互斥量,保护产品缓冲区
	std::mutex pro_mtx;
	std::mutex con_mtx;
	std::condition_variable not_full; // 条件变量, 指示产品缓冲区不为满.
	std::condition_variable not_empty; // 条件变量, 指示产品缓冲区不为空.
} instance; // 产品库全局变量, 生产者和消费者操作该变量.

typedef struct resource resource;


void Producer(resource *ir, int item)
{
	std::unique_lock<std::mutex> lock(ir->mtx);
	while (((ir->write_pos + 1) % bufSize)
		== ir->read_pos) { // item buffer is full, just wait here.
		std::cout << "Producer is waiting for an empty slot...\n";
		(ir->not_full).wait(lock); // 生产者等待"产品库缓冲区不为满"这一条件发生.
	}

	(ir->buf)[ir->write_pos] = item; // 写入产品.
	(ir->write_pos)++; // 写入位置后移.

	if (ir->write_pos == bufSize) // 写入位置若是在队列最后则重新设置为初始位置.
		ir->write_pos = 0;

	(ir->not_empty).notify_all(); // 通知消费者产品库不为空.
}

int Consumer(resource *ir)
{
	int data;
	std::unique_lock<std::mutex> lock(ir->mtx);
	// item buffer is empty, just wait here.
	while (ir->write_pos == ir->read_pos) {
		std::cout << "Consumer is waiting for items...\n";
		(ir->not_empty).wait(lock); // 消费者等待"产品库缓冲区不为空"这一条件发生.
	}

	data = (ir->buf)[ir->read_pos]; // 读取某一产品
	(ir->read_pos)++; // 读取位置后移

	if (ir->read_pos >= bufSize) // 读取位置若移到最后,则重新置位.
		ir->read_pos = 0;

	(ir->not_full).notify_all(); // 通知消费者产品库不为满.

	return data; // 返回产品.
}


void ProducerTask() // 生产者任务
{
	bool ready_to_exit = false;
	while (1) {
		sleep(1);
		std::unique_lock<std::mutex> lock(instance.pro_mtx);
		if (instance.pro_item_counter < ProNum) {
			++(instance.pro_item_counter);
			Producer(&instance, instance.pro_item_counter);
			std::cout << "Producer thread " << std::this_thread::get_id()
				<< " is producing the " << instance.pro_item_counter
				<< "^th item" << std::endl;
		}
		else 
			ready_to_exit = true;
		lock.unlock();
		if (ready_to_exit == true) 
			break;
	}
	std::cout << "Producer thread " << std::this_thread::get_id()
		<< " is exiting..." << std::endl;
}

void ConsumerTask() // 消费者任务
{
	bool ready_to_exit = false;
	while (1) {
		sleep(1);
		std::unique_lock<std::mutex> lock(instance.con_mtx);
		if (instance.con_item_counter < ProNum) {
			int item = Consumer(&instance);
			++(instance.con_item_counter);
			std::cout << "Consumer thread " << std::this_thread::get_id()
				<< " is consuming the " << item << "^th item" << std::endl;
		}
		else
			ready_to_exit = true;
		lock.unlock();
		if (ready_to_exit == true)
			break;
	}
	std::cout << "Consumer thread " << std::this_thread::get_id()
		<< " is exiting..." << std::endl;
}

void Initresource(resource *ir)
{
	ir->write_pos = 0; // 初始化产品写入位置.
	ir->read_pos = 0; // 初始化产品读取位置.
	ir->pro_item_counter = 0;
	ir->con_item_counter = 0;
}

int main()
{
	Initresource(&instance);
	std::thread producer1(ProducerTask);
	std::thread producer2(ProducerTask);
	std::thread producer3(ProducerTask);
	std::thread producer4(ProducerTask);

	std::thread consumer1(ConsumerTask);
	std::thread consumer2(ConsumerTask);
	std::thread consumer3(ConsumerTask);
	std::thread consumer4(ConsumerTask);

	producer1.join();
	producer2.join();
	producer3.join();
	producer4.join();

	consumer1.join();
	consumer2.join();
	consumer3.join();
	consumer4.join();
	return 0;
}

在这里插入图片描述

参考

1、https://www.cnblogs.com/haippy/p/3252092.html
2、https://blog.csdn.net/qq_41681241/article/details/86708303
3、https://blog.csdn.net/h_wulingfei/article/details/104897449

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++实现生产者和消费者模型 的相关文章

  • 用for循环实现delay延时原理

    void Delay10ms unsigned int c 误差 0us unsigned char a b for c gt 0 c c可以不用初始化 xff0c 因为默认传的参数即为初始化 for b 61 38 b gt 0 b fo
  • 解决ROS中运行gazebo出现process has died的情况

    项目场景 xff1a gazebo 1 process has died pid 397 exit code 255 cmd opt ros melodic lib gazebo ros gzserver e ode worlds empt
  • 使用Ventoy制作U盘启动项

    最近在安装linux镜像的时候遇到了使用UltraISO软件制作U盘启动盘无法使用的情况 下面介绍另外一个软件把U盘制作成启动盘Ventoy xff1a 下载地址 xff1a Ventoy 使用方法 xff1a 1 下载好Ventoy xf
  • git 快速入手

    目录 一 xff1a 初次使用git及github 二 xff1a 将github上下载的代码上传到自己的github仓库里 三 xff1a 使用HTTP上传自己写的项目至github git常用指令汇总 使用需求 xff1a 初次接触gi
  • 线程、进程、并发、cpu、gpu的联系

    1 线程和进程的区别 进程 xff1a 一个在内存中运行的应用程序 每个进程都有自己独立的一块内存空间 xff0c 一个进程可以有多个线程 比如在Windows系统中 xff0c 一个运行的xx exe就是一个进程 线程 xff1a 进程中
  • ubuntu系统安装cuda、cudnn、pytorch和libtorch

    1 安装cuda和cudnn 本机安装的cuda版本11 0 2 cudnn版本 v8 0 5 cu11 0 Ubuntu20 04下CUDA cuDNN的详细安装与配置过程 xff08 图文 xff09 ubuntu20 04安装cuda
  • 深度学习语法篇

    一 基本常识 图像的分辨率的通道数 分辨率和通道数是两个不同的概念 分辨率指的是图像的像素数量 xff0c 它反映了图像的清晰度和细节程度 例如 xff0c 一个分辨率为64x64的图像意味着它有64个像素行和64个像素列 xff0c 总共
  • 第二讲:线性表示及坐标

    第二讲 xff1a 线性表示及坐标 一 线性表示 1 线性表示定义 xff1a 设 是线性空间V中的向量 xff0c 若存在V中一组向量 1 xff0c 2 xff0c xff0c n xff0c 及一组数x1 xff0c x2 xff0c
  • 快速理解掌握指针

    p gt next 61 q 像这种语句 xff0c 表示改变了p后面的连接关系 p 61 q gt next 这类语句 xff0c 没改变连接关系 xff0c 只是赋值而已 解读代码中指针所代表的节点之间的前后连接关系 只要输出该指针对应
  • 第三讲:子空间

    第三讲 xff1a 子空间 一 子空间定义 1 子空间 xff1a 设V是数域F上的线性空间 xff0c W是V的子集 xff0c 若对W中的任意元素 xff0c 及数K F xff0c 按V中的加法和数乘有 xff1a 1 xff09 4
  • Qt多线程之线程之间的传递数据

    hpp span class token macro property span class token directive keyword ifndef span MAINWINDOW H span span class token ma
  • 循环队列c代码实现

    循环队列的抽象数据类型 ADT 队列 xff08 Queue xff09 Data 同线性表 元素具有相同的类型 xff0c 相邻元素具有前驱和后继的关系 Operator span class token function InitQue
  • CMake(四):变量

    前面展示了如何定义基本目标和生成构建输出 就其本身而言 xff0c 这已经很有用了 xff0c 但CMake还附带了一大堆其他特性 xff0c 这些特性带来了极大的灵活性和便利性 本章涵盖了CMake最基本的部分之一 xff0c 即变量的使
  • CMake(六):使用子目录

    对于简单的项目 xff0c 将所有内容保存在一个目录中是可以的 xff0c 但是大多数实际项目倾向于将它们的文件分割到多个目录中 通常可以找到不同的文件类型或分组在各自的目录下的独立模块 xff0c 或者将属于逻辑功能组的文件放在项目目录层
  • CMake(九):生成器表达式

    当运行CMake时 xff0c 开发人员倾向于认为它是一个简单的步骤 xff0c 需要读取项目的CMakeLists txt文件 xff0c 并生成相关的特定于生成器的项目文件集 例如Visual Studio解决方案和项目文件 xff0c
  • CNNs系列---AlexNet网络介绍

    CNNs系列 AlexNet介绍 导言AlexNet介绍1 网络结构 1 参数量 计算量和输出尺寸计算公式 2 网络参数解析 2 AlexNet中涉及到的知识点 1 基本概念 2 AlexNet网络结构的贡献 导言 我们将开启关于卷积神经网
  • CNNS:基于AlexNet的分类任务

    CNNS 基于AlexNet的分类任务 数据集介绍1 pokeman数据集介绍2 flower数据集介绍 超参数对模型的影响1 激活函数对模型的影响 1 使用 96 Sigmoid 96 进行训练 2 使用 96 tanh 96 进行训练
  • CNNs: AlexNet补充

    CNNs AlexNet的补充 导言对 96 AlexNet 96 模型进行调整模型不同层的表征其他探索总结 导言 上上篇和上一篇我们详细地讲述了AlexNet的网络结构和不同超参数对同一数据集的不同实验现象 本节 xff0c 我们就Ale
  • 解决“Permission denied, please try again.”的问题

    在Ubuntu的终端输入命令 ssh highlight highlight是本地主机名称提示输入用户密码 当密码输入正确时 xff0c 仍返回错误 xff1a Permission denied please try again 解决的办
  • leetcode学习常用网站

    C 43 43 网站 cplusplus com map find C 43 43 Reference github com leopeng1995 acplusplus Morris Traversal方法遍历二叉树 xff08 非递归

随机推荐

  • arctan对照表

    注 xff1a 实际调用的是C 43 43 的atan2接口 arctan y x resultstd cout lt lt atan2 0 1 lt lt std endl 0std cout lt lt atan2 0 707 0 70
  • 关于optimized out

    根据网络上的说法 xff0c 调试期间如果一个变量的值显示 optimized out xff0c 那么就表明编译器将该变量进行了优化 xff0c 导致其值不可见 解决的方法是 xff0c 设置编译优化选项 xff0c 禁止相关的优化 可以
  • Ubuntu命令行中重复执行一个程序

    以下示例中 xff0c 执行program 10次 xff0c 并将运行日志以追加的方式重定向到log txt文件中 xff0c progam的入口参数是param for i in 1 10 do program param gt gt
  • 技术知识库

    我对自动控制技术发展趋势的理解 对数学理论的运用越来越深入 xff0c 对计算机的依赖越来越高 xff1b 与人们生产生活的契合越来越紧密以至于无法分割 xff1b 越来越向人类思维的本质倾向 心想事成靠拢 xff0c 让少数人的大脑和肢体
  • [AR论文阅读] Tracking Requirements for Augmented Reality

    论文作者 xff1a RONALD AZUMA年份 xff1a 1993论文主题 xff1a 阐述AR系统对6DoF跟踪性能的技术要求 要点 xff1a 三个核心要求 xff1a 高精度 xff0c 低延迟 xff0c 大范围 跟踪精度指标
  • cv::Mat和std::vector的相互转化

    声明 xff1a 代码来自StackOverFlow xff0c 原文链接 span class hljs keyword using span span class hljs keyword namespace span cv span
  • 构建fabMap过程中可能遇到的错误

    1 When OpenCV2 4 9 is not installed the system has OpenCV2 4 8 pre installed in usr lib x86 64 linux gnu and usr include
  • C++处理Ctrl+C中断信号

    span class hljs preprocessor include lt iostream gt span span class hljs preprocessor include lt csignal gt span span cl
  • Ubuntu获取最高权限(su)的方式

    sudo i span class hljs preprocessor 输入当前账户密码 span span class hljs preprocessor 进入su模式 xff08 root权限 xff09 span
  • 头文件被重复包含的危害及解决办法

    头文件被重复包含的危害 1 简单的理解 xff1a 无非就是头文件里有一行 int a 61 1 包含两次就变成了 int a 61 1 int a 61 1 于是变量重复定义 xff0c 报错 类 xff0c 函数同理 而当你写成 ifn
  • acrobat进行OCR文字识别失败

    OCR文字识别失败是因为pdf有一页图片过于华丽 xff0c 无法识别 xff0c 在adobe acrobat报错的时候 xff0c 瞅准这一页的页码 xff0c 然后跳过这一页 xff0c 继续文字识别其他页就可以了 黑底白字识别也会失
  • STL基础篇(适合初学者快速入门)

    1 STL 是什么 作为一个C 43 43 程序设计者 xff0c STL 是一种不可忽视的技术 Standard Template Library STL xff1a 标准模板库 更准确的说是 C 43 43 程序设计语言标准模板库 ST
  • golang 错误处理

    一 defer package main import 34 fmt 34 34 os 34 34 bufio 34 func tryDefer for i 61 0 i lt 100 i 43 43 defer fmt Println i
  • 平台式惯性导航系统简介(持续更新ing)

    惯性导航系统是利用惯性敏感器件 xff0c 通过基准方向 初始位置等信息来确定运载体位置 姿态和速度的自主式航位推算系统 平台式惯性导航系统是与捷联式惯性导航系统相对应的一种导航方式 目录 前言 一 前备知识 1 惯性导航常用坐标系 2 哥
  • C++ 标准模板库(STL)_iterator—— Traits(侯捷老师)

    iterator Traits Traits1 产生背景2 定义2 1 iterator traits中定义的class iterators2 1 iterator traits中定义的non class iterators 3 内嵌类型声
  • C++ 标准模板库(STL)_序列式容器——Vector以及扩容操作(侯捷老师)

    STL Vector容器 Vector1 定义2 数据结构3 vector成倍扩容过程及部分源码3 1 扩容条件3 2 扩容步骤 xff08 3步 xff09 3 3 扩容操作部分源码 insert aux push back 43 ins
  • C++ 标准模板库(STL)_序列式容器—— deque(模拟连续空间)(侯捷老师)

    STL deque 双端队列 deque1 定义2 特点3 deque节点结构 数据组织形式 xff09 4 deque数据结构部分源码定义5 初始化map部分源码6 deque iterator 源码定义6 1 迭代器失效问题 7 pus
  • 常见数据结构——完全二叉树(定义、特征、节点个数的判断以及C++简单实现)

    完全二叉树 完全二叉树1 定义2 特征3 C 43 43 简单实现完全二叉树的节点个数 完全二叉树 1 定义 完全二叉树是由满二叉树而引出来的 xff0c 若设二叉树的深度为h xff0c 除第 h 层外 xff0c 其它各层 1 xff5
  • 什么是状态机(Finite-state machine)?

    有限状态机 有限状态机 FSM 1 什么是 状态 2 什么是状态机 xff1f 3 状态机图怎么画 xff1f 参考 有限状态机 FSM 1 什么是 状态 先来解释什么是 状态 xff08 State xff09 现实事物是有不同状态的 x
  • C++实现生产者和消费者模型

    C 43 43 实现生产者和消费者模型 C 43 43 实现生产者和消费者模型1 实现细节2 单生产者 单消费者模型3 单生产者 多消费者模型4 多生产者 单消费者模型5 多生产者 多消费者模型 参考 C 43 43 实现生产者和消费者模型