<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[inoobkk的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/dovakejin</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; dovakejin]]></copyright><item><title><![CDATA[从golang的sync.pool到linux的slab分配器]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/148496694</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/148496694</guid><author>dovakejin</author><pubDate>Sat, 07 Jun 2025 17:50:45 +0800</pubDate><description><![CDATA[最近学习golang的时候，看到golang并发编程中有一个sync.pool，即对象池，猛地一看这不跟linux的slab分配器类似嘛，赶紧学习记录下这里先总结下设计sync.pool和slab的目的。]]></description><category></category></item><item><title><![CDATA[实现引用计数线程安全的shared_ptr]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/147751857</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/147751857</guid><author>dovakejin</author><pubDate>Wed, 07 May 2025 22:31:33 +0800</pubDate><description><![CDATA[其中，shared_ptr是共享智能指针，可以被多次拷贝，拷贝时其内部的引用计数+1，被销毁时引用计数-1，如果引用计数为0，那么释放其所管理的资源。在网上找到的shared_ptr的手动实现都是线程不安全的，那么如何实现一个引用计数线程安全的shared_ptr呢？c++11引入了三个智能指针，用来自动管理内存，使用智能指针可以有效地减少内存泄漏。，本文在这篇博客的基础上增加了验证代码，并指出原有实现一个潜在的bug。]]></description><category></category></item><item><title><![CDATA[std::mutex底层实现原理]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/147541642</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/147541642</guid><author>dovakejin</author><pubDate>Sat, 26 Apr 2025 21:22:38 +0800</pubDate><description><![CDATA[std::mutex是一个用于实现互斥访问的类，其具备两个成员函数——lock和unlock以下是一个简单例子。]]></description><category></category></item><item><title><![CDATA[条件变量底层实现原理]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/147354623</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/147354623</guid><author>dovakejin</author><pubDate>Mon, 21 Apr 2025 20:30:12 +0800</pubDate><description><![CDATA[在并发编程中，条件变量用来控制线程之间的同步，总的来说条件变量相关的操作主要有两个——wait和notify，在写博客时我有这样一些疑问：1.wait操作是如何实现的，它是如何让线程进入睡眠的2.notiy操作是如何做到通知正在等待的线程的，并且如何做到notify单个线程和notify所有线程的，如果是notify所有线程，那么这些被唤醒的线程可以并行执行吗（多核情况下）3.为什么在调用wait操作时，需要传入mutex互斥锁，而notify时却不用。]]></description><category></category></item><item><title><![CDATA[ubuntu20.04搭建opengl开发环境并运行第一个程序]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/130209702</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/130209702</guid><author>dovakejin</author><pubDate>Mon, 17 Apr 2023 21:55:05 +0800</pubDate><description><![CDATA[参考《opengl编程指南》第四版。]]></description><category></category></item><item><title><![CDATA[linux下tcp服务端与客户端实现]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/129226601</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/129226601</guid><author>dovakejin</author><pubDate>Sun, 26 Feb 2023 14:34:36 +0800</pubDate><description><![CDATA[使用socket完成linux下服务端与客户端的编写，传输层使用tcp协议，服务端使用多进程实现并发。]]></description><category></category></item><item><title><![CDATA[zlib压缩原理]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/129096962</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/129096962</guid><author>dovakejin</author><pubDate>Sat, 18 Feb 2023 09:47:10 +0800</pubDate><description><![CDATA[zlib压缩算法讲解，包括lz77算法和huffman编码]]></description><category></category></item><item><title><![CDATA[c++ const_cast转换运算符与volatile关键字]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/119152349</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/119152349</guid><author>dovakejin</author><pubDate>Tue, 27 Jul 2021 20:26:46 +0800</pubDate><description><![CDATA[const_cast转换运算符用来去除变量的底层const属性，这里的变量的类型是指针或者引用类型，因为普通类型并没有底层const属性这个说法。

const_cast使用实例：代码转自：IT男汉：C++ const_cast用法


#include&lt;iostream&gt;
using namespace std;
void ConstTest1() {
	const int a = 5;
	int *p;
	p = const_cast&lt;int*&gt;(&amp;a);
	(*p)..]]></description><category></category></item><item><title><![CDATA[关于vector容器的deallocator的思考]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/118606356</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/118606356</guid><author>dovakejin</author><pubDate>Fri, 09 Jul 2021 15:04:12 +0800</pubDate><description><![CDATA[从STL源码剖析这本书上得到的vector容器的deallocate函数如下：


void deallocate() {		// 释放所有的分配的内存，为重新开辟一大段空间做准备，因为vector要求连续的数组
		if (start) {
			data_allocator::deallocate(start, end_of_storage - start);
		}
	}

这段代码看起来很合理，就是释放[start, end_of_storage)这一段内存空间。现在继续看data_allocato]]></description><category></category></item><item><title><![CDATA[关于STL中空间配置器中free_list的理解]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/118558949</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/118558949</guid><author>dovakejin</author><pubDate>Wed, 07 Jul 2021 22:44:42 +0800</pubDate><description><![CDATA[freeList是一个元素类型为obj*的数组，freeList[i]代表着一串内存区块链表（注，为了方便说明，把这里的一大块空间称为一个链表，因为它有着与链表类似的表现形式，为了更好的突出链表的形式，上图中的两个区块没有连接在一起。实际上这一块空间是连续的，而链表中的两个节点在内存上不一定是连续的，需要注意）的首地址，每串区块的区块大小是不同的。假设freeList[0]代表一串区块大小为8的区块串，则它有可能是如下的形式



可以看出，在一个区块链表中，每两个obj 对象之间的首地址的差值为一个区块的]]></description><category></category></item><item><title><![CDATA[spawn-fcgi: child exited with: 127可能的原因]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/118524185</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/118524185</guid><author>dovakejin</author><pubDate>Tue, 06 Jul 2021 16:45:23 +0800</pubDate><description><![CDATA[第一种是动态链接库的问题，请参考https://blog.youkuaiyun.com/lucky_huijun/article/details/105165359

第二种是没有正确的输入路径名，下面这样的是错误的


spawn-fcgi -a 127.0.0.1 -p 9001 -f a.out

正确的应该是


spawn-fcgi -a 127.0.0.1 -p 9001 -f /a.out

如果是第二种错误就打自己一巴掌吧^_^
...]]></description><category></category></item><item><title><![CDATA[c++ primer9.32]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/118466176</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/118466176</guid><author>dovakejin</author><pubDate>Sun, 04 Jul 2021 19:39:10 +0800</pubDate><description><![CDATA[网上的解释为：



参考链接：链接

不过我试了下，下面的代码是可以的，暂时不知道原因


#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;list&gt;
#include &lt;deque&gt;
#include&lt;forward_list&gt;
using namespace std;

int main()
{
	vector&lt;int&gt; vi = { ]]></description><category></category></item><item><title><![CDATA[forward_lsit的erase操作为什么是删除指定的迭代器之后的元素]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/118465289</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/118465289</guid><author>dovakejin</author><pubDate>Sun, 04 Jul 2021 18:27:03 +0800</pubDate><description><![CDATA[问题描述：在forward_list的这个容器中，没有erase接口，只提供了erase_after这个接口。其中erase _after(p)为删除迭代器p指向的位置之后的一个元素。那么为什么不能直接删除当前迭代器指向的元素呢。

首先找到STL中slist.h，可以看到


iterator erase_after(iterator __pos) {
    return iterator((_Node*) this-&gt;_M_erase_after(__pos._M_node));
  }

于是]]></description><category></category></item><item><title><![CDATA[vector的erase函数的陷阱]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/118407777</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/118407777</guid><author>dovakejin</author><pubDate>Fri, 02 Jul 2021 11:05:56 +0800</pubDate><description><![CDATA[在下面的代码中，我试图用erase删除vector中的所有值为偶数的元素。根据c++primer 11，erase的返回值是指向被删除元素之后元素的迭代器。根据我的想法，我认为既然是删除一个元素，那么该被删除元素之后的所有元素都会往前移动一个位置，因此在删除该元素后，指向该被删除元素的迭代其器变成指向下一个元素的迭代器，但是却出现了错误。晚上的解答是使用erase(p)之后，p变为无效状态。


#include &lt;iostream&gt;
#include &lt;string&gt;
#incl.]]></description><category></category></item><item><title><![CDATA[ｃ／ｃ＋＋判断字节序类型]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/117771282</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/117771282</guid><author>dovakejin</author><pubDate>Thu, 10 Jun 2021 11:09:48 +0800</pubDate><description><![CDATA[代码来自《Ｌｉｎｕｘ高新能服务器编程》
#include&lt;stdio.h&gt;

void byteorder()
{
	union
	{
		short value;	// short为2个字节，共16位 
		char union_bytes[sizeof(short)];
	}test;
	test.value = 0x0102;
	if((test.union_bytes[0] == 1) &amp;&amp; (test.union_bytes[1]==2))
	{
		printf("b]]></description><category></category></item><item><title><![CDATA[c语言strcat函数]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/117753696</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/117753696</guid><author>dovakejin</author><pubDate>Wed, 09 Jun 2021 20:38:42 +0800</pubDate><description><![CDATA[头文件：#include&lt;string.h&gt;
功能：连接两个字符串
函数原型：char *strcat(char *dest, const char *src);
注意事项：dest需要足够大的空间容纳拼接后的字符串
代码示例1：错误的用法，空间分配不足
#include&lt;iostream&gt;
#include&lt;vector&gt; 
#include&lt;string.h&gt;
#define _CRT_SECURE_NO_DEPRECATE		// vs2017中屏蔽警告]]></description><category></category></item><item><title><![CDATA[c++ 中auto与decltype]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/117391310</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/117391310</guid><author>dovakejin</author><pubDate>Sat, 29 May 2021 21:26:05 +0800</pubDate><description><![CDATA[#include&lt;iostream&gt;
using namespace std;
int main()
{
	const int i = 42;
	auto j = i;
	j = 1;
	cout&lt;&lt;j&lt;&lt;endl;				// auto一般会忽略顶层const 
	const auto &amp;k = i;			// 明确指定为顶层const 
	//k = 1; 							// k是const引用 
	auto *p = &amp;i;					// p的类型.]]></description><category></category></item><item><title><![CDATA[移动构造函数和拷贝构造函数的匹配规则]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/116860331</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/116860331</guid><author>dovakejin</author><pubDate>Sat, 15 May 2021 20:17:24 +0800</pubDate><description><![CDATA[参考c++ primer第五版的StrVec类
拷贝构造函数是
StrVec::StrVec(const Strvec&amp; s){...}

移动构造函数是
StrVec::StrVec(Strvec&amp;&amp; s) noexcept {...} 

疑问：在初始化时是如何选择拷贝构造函数和移动构造函数的
如
StrVec s; // 使用默认构造函数初始化
StrVec s1(s); // 这里调用拷贝构造函数还是移动构造函数？

答案：c++ primer第五版477页
如果一个类既有拷]]></description><category></category></item><item><title><![CDATA[蓝桥杯 算法提高 拯救Andy BFS C++]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/116806285</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/116806285</guid><author>dovakejin</author><pubDate>Fri, 14 May 2021 21:16:13 +0800</pubDate><description><![CDATA[思路：
首先将所有的绿洲加入队列中，每次从队列中取一个元素，查询周围的8个坐标（需要注意边界条件）的最小距离是否可以被更新，如果相邻坐标被更新则将该坐标加入队列中。
代码：
#include&lt;iostream&gt;
#include&lt;vector&gt;
#include&lt;queue&gt;
using namespace std;
#define MAX 100000000
struct Pos
{
	int x, y;
};
void bfs(queue&lt;Pos&gt;&amp]]></description><category></category></item><item><title><![CDATA[隐式销毁一个内置指针类型成员不会delete它所指向的对象]]></title><link>https://blog.youkuaiyun.com/dovakejin/article/details/116796402</link><guid>https://blog.youkuaiyun.com/dovakejin/article/details/116796402</guid><author>dovakejin</author><pubDate>Fri, 14 May 2021 16:35:38 +0800</pubDate><description><![CDATA[隐式销毁内置指针类型成员
Test.h
使用默认析构函数
#pragma once
#include&lt;iostream&gt;
using namespace std;
class Test
{
public:
	Test() = default;
	Test(int dt) : data(dt) {}
	Test(int dt, Test* p) : data(dt), ptest(p) {}
	void printData()
	{
		cout &lt;&lt; data;
	}
private]]></description><category></category></item></channel></rss>