自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(86)
  • 收藏
  • 关注

原创 【设计模式】

听别人讲过这样的一个例子,建造玩偶,玩偶存在头部,身体,双手双脚,6个部分,而建造者模式便可以控制这些细节,得到的玩偶是大头儿子还是小头爸爸。该模式的核心思想是限制类的实例化过程,使类在整个应用程序中只能存在一个实例,且通常包含一个静态成员变量来保存这个实例,并且提供一个静态方法来获取这个实例,避免了创建对象的开销,保持数据的一致性。代理模式是一种结构型设计模式,用于控制对其他对象的访问,代理充当了客户和实际对象之间的中介,通过代理对象,客户可以简介的访问实际对象,并在访问过程中添加额外的操作。

2023-07-21 00:45:00 162

原创 生产者消费者模型

设置了容器,将卡的钱数放入容器中,在容器中寻找和钱数相同的用户,如果存在说明卡被占用,如果不存在可以进行转账,但是两张卡钱数一样就会发生死锁,所以呢我们可以使用卡的地址,卡的钱数可以相同,但是创建卡的地址肯定不同,所以就解决了死锁问题。生产者消费者相信大家都学过,而这个模型也和名字一样,生产者生产数据,消费者消费数据,这里存在一个队列,生产者生产的数据存放在队列中,消费者消费数据从队列中消费,而容器的大小是固定的,当容器中数据个数大小到达上限时,生产者不能生产,如果容器中没数据,消费者不能消费。

2023-06-19 21:35:32 313

原创 C++线程库(2)

在C++线程库(1)的博客中说了互斥量只能解决多个线程访问共享资源的问题,但是很明显没有次序感,而线程安全就是不同线程访问资源但是得到的结果是固定的就这就线程安全,所以为了保证线程安全,互斥锁一般与条件变量搭配使用。我们试着编写一个程序,创建三个线程,调用funa,funb,func函数,依次输出1,2,3,4,5,6也就是线程a输出1,4,7等,线程b输出2,5,8,线程C输出3,6,9等输出到100。),我们举例tha线程获取到锁,他获取到锁之后呢ready为false,进入循环,进入cv等待函数。

2023-06-18 01:00:00 575

原创 C++线程库(1)

比如说你去买衣服,有一个试衣间,有两个人要试衣服,一次试一件衣服,而每个人要试好多件衣服,这就出现了竞争,这一个试衣间只能一个人使用,你使用的时候他不能使用,他使用的时候你不能使用,当然为了避免出现两人一起使用的情况,我们会发现门上都有一个锁,这就可以理解为互斥锁,当你试衣服的时候,或获取锁,也就是将门锁起来,锁起来之后其他人无法获取锁而打开门,你用完之后出来就把锁打开,其他人就可以获取锁了。所以呢出现了递归锁。阻塞:读数据,如果没有数据传输过来,就会阻塞住,等待数据传输过来,进行读取,侧重于等待的过程。

2023-06-16 01:00:00 237

原创 lambda表达式

该代码中在函数func中使用lambda表达式对全局变量进行了操作,而捕获方式是不捕获任何变量,捕获是针对局部区域内的,所以不存在对全局变量进行捕获,可以在lambda表达式中对全局变量进行操作,但是如果将g_max变成a变量,就会报错,因为使用的是[],不捕获任何变量,但是可以使用形参和表达式函数体中的变量。我们创建一个list容器,并且初始化,删除其中的偶数,就可以用remove_if函数,该函数的参数中使用lambda表达式返回是否为偶数,是偶数就进行删除,不为是偶数就不删除。params是参数表;

2023-06-13 01:00:00 361

原创 智能指针(2)

这里我只画了pc对象的结构,其结构都是一样的,创建pa对象的时候,其有三个成员对象,一个是删除器,另外两个是指针,指向堆区的空间,其中一个指针指向我们的Int对象,另一个指向我们在堆区创建的计数器对象,计数器中存在一个指针和两个计数器,其指针指向我们的Int对象,两个计数器分别是_Uses和_Weaks,这里个计数器分别是共享型智能指针和弱引用智能指针。也没有太多要说的,主要是其结构,上面说了计数器类型,其有三个成员对象,分别是ptr指针,指向资源对象,而另外两个便是整型计数器,但是其写法是这样的。

2023-06-11 01:00:00 365

原创 智能指针(1)

return 0;我们创建了唯一性指针对象pa,指向船舰的PtrInt对象,可以通过指针来调用类的成员方法。并且会自动析构。错误使用//C }A:使用智能指针管理全局变量是没有意义的,因为程序结束后,指针才销毁,都不如直接定义一个全局变量,其会在程序结束时自动销毁。(智能指针主要依赖局部对象来释放)B:对象本身就是在栈中,而智能指针是处理堆区堆存,所以是错误的。C:该方法本质上不是错误的,因为你用了裸指针,如果发现用了指针还没释放,就会释放两次,导致程序崩溃。

2023-06-08 15:54:52 681

原创 STL(结)

这里桶中结点个数是10个,所以存放结点是这样存放的,关键码对10取余,得到的结果是多少就存放在那个结点后面,存放的方式便是链表。而如果数据量太大的情况下,而桶中结点个数很少,这样导致一个结点后的元素个数很多,遍历时元素效率就很低,所以桶的也会进行扩容(更改10),然后重构哈希表(桶)。而每当结点个数等于桶中元素个数时就会扩容。set容器智能存放一种类型,其底层也是红黑树,遍历是有序的,其插入的参数有两个,一个是要插入的关键码类型,另一个是bool类型,可以通过bool类型的返回值判断是否插入成功。

2023-06-06 16:28:50 299

原创 C++11右值

/error 不具名对象为右值, const Int & c = Int(3);return 0;无论声明左值引用还是右值引用都必须立即进行初始化,因为引用类型本身并不拥有所绑定对象的内存,只是该对象的一个别名,通过右值引用的声明,该右值又重获新生,其生命周期与右值引用类型名的生命周期一样,只要改右值引用名话或者,改右值临时两就一直存活下去。

2023-06-04 14:21:30 587

原创 【STL(2)】

注意双端队列只能通过vector来实现,因为只有vector是连续的空间结构,而优先级队列其实虽然叫队列但是其不满足先入先出的条件,像是数据类型中的堆,每次出队是队列中优先级最高的元素出队,而优先级可以通过元素大小进行定义。我们不看上面Add类的时候就会觉得我们直接调用了函数,实际上是重载了函括号的重载,这就是函数对象,也叫仿函数,有时也叫函子,我们这里的举例因为两个参数,所以是二元仿函数。vector中没有直接的排序,需要调用系统的排序函数,而且只能是从小到大的排序,但是要是想要从大到小的呢?

2023-06-02 04:00:00 298

原创 STL库(1)

vector是可以改变大小的数组的容器。其内存结构和数组一样,使用连续的存储空间,也就可以使用指针指向其元素,通过偏移量来访问存储空间中的元素。和数组不同之处在于vector的大小可以动态的变化,容器可以自动扩容存储空间。vector使用一个动态分配的连续存储空间来存储元素,在插入新元素的时候也可能需要重新分配存储空间,也就意味着每次扩容都需要将其元素重新移动到新的存储空间中,很显然这效率是非常低的,为此不会每次像容器中添加元素都重新分配。

2023-06-01 01:00:00 580

原创 【异常捕获】

在throw中捕获到异常之后会通过异常类来创建一个异常对象来通过catch来解决这个异常,如果没有解决这个异常会跳出这一层,谁来调用这一部分,在上层来找catch来解决这个问题,如果在主函数中都没找到,那么会通过操作系统来终止程序处理。在C++语言本身抛出异常(new失败,STL),第三方库,系统库的接口抛出异常时,可以使用异常捕获机制。异常时程序可能检测到的,运行时不正常的情况,如存储空间耗尽,数组越界等,可以预见可能发生在什么地方但不知道在什么时候发生的错误。例如上面两数相除的程序,分母为0便是错误。

2023-05-30 01:00:00 588

原创 类型转换(2)

其输出结果是的d,c,b,a,0x61626364,我们的计算机是小端存储,所以地址存放低位,高地址存放高位,cp为低地址,存放16进制的64,而16进制的64转换成10进制就是100,正好是字母d的ASK码值,然后依次移动1字节,也就是63,62,61对应cba,对应输出结果是dcba。思考上面代码输出结果是什么?运行上面一段代码就可以应正我们的结论,在指针和引用转换的前提下进行上行转换,动态转换和静态转换都是一样的,但是在值转换的时候,动态转换就会报错,但可以将派生类对象转换为基类右值引用。

2023-05-27 01:00:00 729

原创 类型转换(1)

将Circle的指针强转成Square类型的指针,输出结果是什么,首先两个类的大小是相同的但是Circle中radius是float类型,Square中length是int类型,所以呢其解析方式不一样,将int类型的12解析成float类型,输出结果为1094713344。rd移动move转换呢,他可以识别常性,其内部是叠加的,常性左值叠加右值仍然是一个常性右值引用,但是没有处理常性右值引用的函数,所以调用的是常性左值引用。我们大致可以这么理解,可以取地址的值为左值,不可以取地址的值为右值。

2023-05-23 01:00:00 380

原创 纯虚函数与抽象类

在上一次博客中写到了这么一段代码:我们发现这段代码的问题出在析构的时候只会析构obj对象,不会析构Base对象,这是什么原因呢?因为在编译过程中op是obj类型的指针,所以就将op和obj类型进行了绑定,析构的时候同样也就只析构了obj类型,造成了内存泄漏。但是怎么解决这个问题呢,我们可以给obj类的析构函数加上virtual关键字,将其变成一个虚函数,这样析构的时候就是动态联编,析构时查看虚表看其指向的是哪个对象的析构函数,然后进行析构。当你的类的成员函数中存在虚函数,就需要将其析构函数设置成虚函数。

2023-05-20 01:00:00 330

原创 多态与虚函数(补)

很显然我们创建Base对象的时候首先会创建obj对象,所以首先会调用obj的构造函数,此时虚表指针指向obj的虚表,所以add(12)调用的是obj的add函数,然后创建完成之后创建Base对象,此时虚表指针指向Base虚表,所以此处的add查找的是Base的add,然后析构开始进入Base的析构函数(重置虚表指针),在~Base的时候调用add调用的是本类型的add函数,然后析构基类,在析构派生类的时候虚表指针已经被重置,指向了obj的虚表,所以析构基类时查找的也是obj的虚表。

2023-05-16 00:45:00 285

原创 多态与虚函数

如图便是三个类的虚表,实在编译时就确定了的,例如obj派生出了Base类,所以Base的虚表就是将obj的虚表拷贝了一份然后进行同名覆盖,而在创建对象的时候,我们以创建Test对象为例,创建该对象首先创建Base,而创建Base需要创建obiect,而当类中有虚函数时类的大小就会多4(32位)字节,用于存放指向虚表的指针,创建Test时,指针首先指向object的虚表,然后指向Base的虚表,最后指向Test的虚表,根据其构建顺序。函数的重载,运算符的重载,属于编译时的多态性。

2023-05-13 00:00:00 468

原创 C++面向对象编程

类的数据成员多为私有的,不能从外部进行操作,因此需要通过公有的成员函数进行操作赋值,而构造函数便是再创建对象的同时进行初始化的函数,注意只能初始化一次。创建对象初始化对象类型转换函数名同类型名无函数返回类型,此处并非void,即什么也不写。其实构造函数本质上存在返回类型,同类名,返回的就是我们创建的对象。程序运行时,当对象被创建时自动调用构造函数,并且只能调用一次,生存期也就仅仅这一次调用。

2023-05-09 09:56:05 1010

原创 IO复用函数的使用

其次,epoll 把用户关心的文件描述符上的事件放在内核里的一个事件表中。fd拷贝呢,select和poll是每次调用函数时,将整个集合的数据拷贝一份到内核中,内核进行运算得到有没有就绪的描述符,存在就绪描述符我们将进行下一步重新遍历寻找就绪的描述符并且做处理,而epoll呢在eoill_ctl函数时就将数据从拷贝进了内核,之后运行epoll函数时就不需要进行拷贝,内核会直接将就绪描述符存放进evs数组中,后面也不需要进行整体遍历,直接进行处理该数组即可。为什么IO效率是O(1)呢?

2023-03-19 13:37:39 171

原创 【HTTP协议与Web服务器】

浏览器与Web服务器再应用层通信使用的是HTTP协议,而HTTP协议在传输层使用的是TCP协议。那么浏览器需要和web服务器进行三次握手建立连接之后才能发送HTTP请求报文,服务器收到请求保温,向浏览器回复HTTP应答报文。浏览器服务器建立连接之后,如果两次以上的请求复用同一个TCP连接,则称之为长连接。如果浏览器发送一次请求报文,服务器回复一次应答就断开连接,下次交互重新进行三次握手建立连接,这种称之为短连接。现如今大多数为长连接,可以减少网络中的同步报文,也使得服务器的响应速度变快。

2023-03-10 17:49:22 739

原创 【Tcp和Udp】

所以发送端就会有一个发送窗口,这个发送窗口的大小是由接收端填充的接收通告窗口的大小决定的,并且窗口的位置会随着发送端数据的发送和接收到接收端对数据的确认而不断的向右滑动,将之称为滑动窗口。交互数据仅包含很少的字节。但 IP 层只能提供尽最大努力的服务,也就是说,TCP 下面的网络所提供的是不可靠的传输。双方都必须为连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。Tcp字节流的特点,发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据从的发送和接收时没有边界限制的。

2023-03-04 10:47:45 355

原创 【socket网络编程】

大端模式是指一个整数的高字节位存储在内存的低地址处,低位字节存储在内存的高地址处。返回值是实际读到的字节数,如果recv()返回值为 0, 说明对方已经关闭了 TCP 连接。通常,人们习惯用点分十进制字符串表示 IPV4 地址,但编程中我们需要先把它们转化为整数方能使用,下面函数可用于点分十进制字符串表示的 IPV4 地址和网络字节序整数表示的 IPV4 地址之间的转换。connect()方法一般由客户端程序执行,需要指定连接的服务器端的 IP 地址和端口。TCP提供的是面向连接的可靠的字节流服务。

2023-03-02 18:13:15 171 1

原创 【计算机网络基础】

如果电脑适配器换了,我们换了一台适配器,那我我们对应的MAC地址也就发生了改变,因此局域网中某个主机的地址不可能告诉我们这台主机位于什么地方,因此寻找主机位置还得通过ip地址进行查找。前者是32位,由“,”分成四个段,每个段是8位(0~255),由十进制表示。网络是由若干结点和链接这些结点的链路组成,网络中的结点可以是计算机,交换机,路由器等设备。TCP:传输控制协议,一种面向连接的,可靠的,基于字节流的传输层通信协议。应用层,传输层,网络层,数据链路层,(物理层)网络设备:交换机,路由器,集线器。

2023-02-27 10:20:01 295

原创 线程的创建与同步

此处要注意:例如线程5,我们将i的地址赋值给线程5时,此时i为4,但是当线程获取i的值时,i已经进入了我们第二次获取退出信息的循环,此时i=0,所以线程5才会输出0。线程的同步指的是一个线程在对某个资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作,其他线程才可以操作,也就是协同步调,让线程按预定的先后顺序进行运行。以上程序我们有五个线程,每个线程打印三次,将主程序中的i的地址传递给我们的线程,线程获取i的值将其打印。等待thread指定的线程退出,线程未退出时,该方法阻塞。

2023-01-06 16:43:39 191

原创 进程间通信

进程间通信:管道 ,信号量,共享内存,消息队列,套接字。(信号量,共享内存,消息队列)同步机制:管道 消息队列。管道写端写满阻塞,管道为空,读端阻塞。同步:同一时刻只能一个进程访问资源,若资源被占用程序就会被则色,对程序的控制同步。

2022-12-28 18:22:26 450

原创 链式哈希表

已知一组关键字为{19,14,23,01,68,20,84,27,55,11,10,79},哈希函数为H=keyMOD13,这样呢我们的哈希地址就是0~12,将19对13取余为6,将19存放在地址为6的页表中,14放入1中,23放入10中,接着就会发现01对13取余也是1,发生了哈希冲突,14已经放入了1中,因此我们就一直向后移动,2为NULL,我们就将01放入地址为2的页表中,就是这种方法,向后遍历,直到找到没有存放关键字的地址,将关键码放入其中即可。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

2022-12-21 18:04:21 412

原创 【AVL树】

一棵AVL树或者是空树,或者是具有谢下列性质的二叉搜索树:他的左子树和右子树都是AVL树,且左子树和右子树的高度只差的绝对值不超过1.如上图,左边的二叉搜索树每个结点的左右子树高度差的绝对值小于1,所以是AVL树,右边的树不是每个结点的左右子树高度差的绝对值小于1所以不是AVL树。每个结点附加一个数字,给出该结点右子树的高度减去左子树的高度所得的高度差。这个数字既是为结点的平衡因子balance。根据AVL树的定义,任何一个结点的平衡因子只能取-1,0,1。如果一个结点的平衡因子的绝对值大于1,则这颗

2022-12-05 13:28:14 293

原创 信号与进程间通信

该函数我们是约定接收到命令之后调用fun函数使用,我们可以发现使用该函数,第一次接收到信号之后会执行输出命令,第二次接收命令之后会默认操作。

2022-11-30 17:36:41 264

原创 二叉搜索树

从二叉排序树中查找一个关键码:我们知道左子树的关键码必然小于根节点的关键码,根节点的关键码必然小于右孩子的关键码。所以遍历时仅仅需要判断要查找的关键是否大于根节点的关键码,大于在右边找,继续判断右子树的根节点关键码与要查找的关键码大小,反之在左子树进行查找。如上三图,如果一颗而擦函数进行中序遍历,可以按从小到大的顺序,将各节点关键码排序起来,所以也称二叉搜索树为二叉排序树。一棵二叉搜索出存在三个指针,左右孩子和双亲指针,还有一个关键码。二叉搜索树又叫二叉排序树,其或者是一棵空树。

2022-11-28 22:21:33 172

原创 进程替换与复制

进程替换:把当前进程换为其他进程执行。(其他进程:创建新进程,生成可执行程序,装在进内存)进程替换替换的是进程实体。PCB使用以前的只是修改。

2022-11-26 16:22:04 515

原创 赫夫曼树赫夫曼编码的创建

下图的结点均为叶子节点,我们首先在其中找到权值最小的两个结点,构造一棵而二叉树,比如下面结点我们以做一个左孩子权值为3右孩子权值为5,双亲权值为8的二叉树,然后将权值为8左孩子和右孩子编号为7和1的结点加入下面结点中,就这样选过的不再继续选,将新建立的结点加入其中,每次选出权值最小的两个结点,一直循环下去,直到遍历完所有的结点即可。从树的一个结点到另一个结点之间的分治构成这两个结点之间的路径,路径上的分支数目称作路径长度。我们发现不同路径权值相同,其带权路径长度不同,而最小的便是我们的赫夫曼树。

2022-11-24 15:24:19 388

原创 二叉树的建立和遍历

在二叉树的存储中,我们发现在创建二叉树函数的时候,,它的参数是char* &str,此处的&是c++中的引用,什么是引用呢?格式为:类型 &引用变量名 = 已定义过的变量名。例如:,此处的引用b便是a的重命名,怎么理解呢,其实a,b指的是同一个变量,a,b只是他不同的名字。此处为什么用引用呢,如果去掉引用会发生什么呢?在数组元素等于ABC##DE##F##G#H## 的时候,输出值会发生错误,发现只在abc之间,不会遍历到后面的元素。怎么样的思路呢,我们递归调用函数时,比如A结点接下来进入左孩子调用

2022-11-22 21:14:08 2898

原创 【操作文件的系统调用】

在上一篇讲述僵尸进程的文章中对文件的系统调用做了一点点的代码讲述,这篇文章对操作文件的系统调用进行细节讲述。

2022-11-19 20:01:43 712

原创 分治策略与递归

例如:对于n个元素的排序问题,当n=1时,不需要任何计算,当n=2时,只要做一次比较即可排序好,n=3时,只要进行两次比较即可,当n越来越大,这个问题的就不那么容易处理了。要想直接解决一个较大的问题,比较困难。,便于各个击破,分而治之,如果原问题可以分割成k个子问题,1

2022-11-18 20:59:26 460

原创 【二叉树的存储及遍历】

树是由n(n>=0)个结点组成的优先集合。如果n等于0,称为空树;但如果n>0,则1)有一个特定称为根的结点,他只有直接后继,没有直接前驱。2)除根节点之外的其他节点分为m(m>=0)个互不相交的有限集合,每个集合又是一棵树,并且称之为根的子树。每个子树的根结点有且只有一个直接前驱,但是可以有0个或多个直接后继。

2022-11-17 16:14:45 460

原创 【僵尸进程和文件系统调用】

一个进程的信息都在PCB中保存,所以一个进程的页表信息也在PCB中保存,(一个进程的创建先出现PID,接着才会出现进程实体。僵尸进程:子进程先于父进程结束,父进程没有回收子进程,子进程进入僵尸进程。子进程的退出,父进程未获取子进程的退出码,所以子进程进入僵尸进程。父进程通过wait命令等待子进程结束之后获取子进程的退出码然后父进程运行。孤儿进程:父进程先于子进程结束,子进程的父进程由init进程接管子进程。子进程结束之后父进程获取子进程的退出码便不会出现僵尸进程。4G供内核1G,用户态的3G,

2022-11-16 17:47:59 344

原创 【进程复制】

输出六个程序刚开始进入进程复制时 ,i都等于0,我们首先执行父进程,父进程先输出一个A,再次进入循环,父进程又一次进行分裂,分裂之后的父子进程i=1,所以此处的父子进程都会输出一个A,第一次分裂之后的父进程输出三个A,再看第一次分裂之后的子进程,同父进程一样,先输出一个A,再次进入循环,再次分裂,分裂的两个程序都输出A,所以第一次分裂的子进程输出三个A,随意总共输出6个A,如图。此处是三个A,考察返回值。此处输出两个A,程序刚开始先进行复制,父进程继续向下运行,输出一个A,子进程也继续输出一个A。

2022-11-15 17:32:44 369

原创 迷宫(maze)

首先肯定要输出二维数组,知道原数组棋盘,接着操作棋盘,紧接着输出棋盘。操作棋盘函数中首先判断首先棋盘是否是通路,什么是通路,是通路的话便是四个方向有至少一个方向可以走,走一步进行一次入栈,若找不到通路开始出栈,每走一步留一个足迹,知道最终走到出口。1)思考迷宫的结构体(元素):一个二维数组,一个移动的小人,小人结构体又存在移动的方向,小机器人的位置,移动的步数 而位置的结构体的又有行和列两个因素。2)因为迷宫需要用栈进行操作。此处用到栈,栈在以前文章中存在,此处不做展示。

2022-11-14 11:06:14 470

原创 【计算机理论基础】

进程:一个正在运行的程序。进程=程序+数据+PCB。PCB:进程控制块,是进程存在的唯一标识。用来描述进程的属性信息。系统是根据PCB来对并发执行的进程进行控制和管理的。一个程序的启动,先出现PCB,再有进程。一个进程的消失,先进行进程实体的消失,接下来才会有伴随着PCB的销毁。系统正在运行的程序称为进程。是操作系统资源分配和调度的基本单位。

2022-11-09 15:42:05 301

原创 队列(queue)

然而循环的概念又从何而来呢,很显然根据上面移动头指针的方式,将会浪费前面的内存,因此我们将队头和队尾连接起来,设置成一个环形,这样也就避免了浪费,连起来也就得到了所谓的循环概念。假如只是用单链表去实现链式队列,则队尾插入(尾插),队头出(头删),这时,我们会要求头删的时间复杂度O(1),尾插的时间复杂度为仍为O(1),但是如果是上述单链表,找到尾结点需要遍历整个单链表,尾插的时间复杂度为O(n),很显然不符合要求为此做一修改,但是在这里,我们用顺序表实现的不叫顺序队列,而叫循环队列。

2022-11-08 11:32:52 272

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除