自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(151)
  • 资源 (12)
  • 问答 (1)
  • 收藏
  • 关注

转载 Linux 的 IO 通信 以及 Reactor 线程模型详解

Linux 的 IO 通信 以及 Reactor 线程模型详解IO 通信模型我们先要来谈谈 I/O 通信。说到 I/O 通信,往往会提到同步(synchronous)I/O 、异步(asynchronous)I/O、阻塞(blocking)I/O 和非阻塞(non-blocking)I/O 四种。有关同步、异步、阻塞和非阻塞的区别很多时候解释不清楚,不同的人知识背景不同,对概念很难达成共识。本文讨论的背景是 Linux 环境下的 Network I/O。一次 I/O 过程分析对于一次 Network

2021-09-23 23:37:03 233

转载 epoll全面讲解:从实现到应用

epoll全面讲解:从实现到应用什么是epoll?或者说,它和select有什么区别?什么是select?有的朋友可能对select也不是很了解啊,我这里稍微科普一下:网络连接,服务器也是通过文件描述符来管理这些连接上来的客户端,既然是供连接的服务器,那就免不了要接收来自客户端的消息。那么多台客户端(不出意外,本文的客户端指的是万能并发),消息那么的多,要是漏了一条两条重要消息,那也不要用TCP了,那怎么办?前辈们就是有办法,轮询,轮询每个客户端文件描述符,查看他们是否带着消息,如果带着,那就处理一

2021-09-22 21:36:37 350

原创 linux select函数解析以及示例

linux select函数解析以及示例背景​ linux下的I/O操作定义:在我看来,I/O是指数据流的操作,比如说网络编程的I/O操作,串口的读写等等可以称为I/O操作。在linux系统中一共有下面五种I/O操作模式。阻塞I/O(blocking I/O)非阻塞I/O (nonblocking I/O)I/O复用 (I/O multiplexing)信号驱动I/O (signal driven I/O (SIGIO))异步I/O (asynchronous I/O (the POSIX

2021-09-18 21:35:37 893

转载 彻底搞懂TCP协议:从 TCP 三次握手四次挥手说起

彻底搞懂TCP协议:从 TCP 三次握手四次挥手说起前言​ 说到 TCP 协议,相信大家都比较熟悉了,对于 TCP 协议总能说个一二三来,但是 TCP 协议又是一个非常复杂的协议,其中有不少细节点让人头疼点。本文就是来说说这些头疼点的,浅谈一些 TCP 的疑难杂症。那么从哪说起呢?当然是从三次握手和四次挥手说起啦,可能大家都知道 TCP 是三次交互完成连接的建立,四次交互来断开一个连接,那为什么是三次握手和四次挥手呢?反过来不行吗?疑症(一) TCP的三次握手、四次挥手​ 下面两图大家再熟悉不过

2021-09-17 20:12:45 206

原创 windows 内存泄漏检测工具之 VLD

windows 内存泄漏检测工具之 VLD​ VLD(Visual Leak Detector)内存泄漏一直是一个令人头疼的问题,Visual Leak Detector工具在处理内存泄漏时非常好用,简单介绍一下Visual Leak Detector。​ Visual Leak Detector是一个开源的,免费的,健壮的又使用起来很简单的内存泄漏检测系统,支持vs2008-vs2015,支持C和C++的工程。​ 下载地址:https://archive.codeplex.com/?p=vld

2021-08-18 21:53:30 1118

原创 c/c++使用 CRT 库查找内存泄漏

c/c++使用 CRT 库查找内存泄漏原理malloc微软提供crt库的时候,dbg版分配的内存是记录了文件和位置的。#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)以前调用malloc的地方现在使用_malloc_dbg,传入了当前的文件路径和行号,分配的堆类型为_NORMAL_BLOCK。new对于new开启宏是没有用的,我们看ctrdbg.h中的源码,对于new的重载定义如

2021-08-17 23:32:07 591

转载 malloc和free的实现原理解析

malloc和free的实现原理解析​ C语言中使用malloc可以分配一段连续的内存空间。在c/c++开发中,因为malloc属于C标准库函数,经常会使用其分配内存。malloc是在堆中分配一块可用内存给用户。作为一个使用频繁的基础函数,理解清楚其实现原理很有必要,因此本文主要探讨malloc的具体实现原理,以及在linux系统中这该函数的实现方式。进程地址空间​ 如上图所示在一个32位系统中,可寻址的空间大小是4G,linux系统下0-3G是用户模式,3-4G是内核模式。而在用户模式下又分为

2021-08-14 10:51:00 1127

转载 Linux中的内存管理机制

Linux中的内存管理机制​ 程序在运行时所有的数据结构的分配都是在堆和栈上进行的,而堆和栈都是建立在内存之上。内存作为现代计算机运行的核心,CPU可以直接访问的通用存储只有内存和处理器内置的寄存器,所有的代码都需要装载到内存之后才能让CPU通过指令寄存器找到相应的地址进行访问。地址空间和MMU​ 内存管理单元(MMU)是硬件提供的最底层的内存管理机制,是CPU的一部分,用来管理内存的控制线路,提供把虚拟地址映射为物理地址的能力。​ 在x86体系结构下,CPU对内存的寻址都是通过分段方式进行的

2021-08-14 10:31:30 642

转载 自己动手实现一个malloc内存分配器

自己动手实现一个malloc内存分配器对内存分配器透彻理解是编程高手的标志之一。​ 如果你不能理解malloc之类内存分配器实现原理的话,那你可能写不出高性能程序,写不出高性能程序就很难参与核心项目,参与不了核心项目那么很难升职加薪,很难升级加薪就无法走向人生巅峰,没想到内存分配竟如此关键,为了走上人生巅峰你也要势必读完本文。​ 现在我们知道了,对内存分配器透彻的理解是写出高性能程序的关键所在,那么我们该怎样透彻理解内存分配器呢?还有什么能比你自己动手实现一个理解的更透彻吗?​ 接下来,我

2021-08-13 00:02:00 561

原创 windows的malloc到virtualAlloc的调用

windows的malloc到virtualAlloc调用​ 先介绍下基本知识Win32 内存结构首先要搞清楚【虚拟内存、交换文件、页面文件、RAM、物理存储、虚拟地址空间】这几个概念!虚拟内存是操作系统的内存管理方式,对上层应用屏蔽了页面文件与RAM的区别与调度方式。先看看操作系统,再来说吧!Windows操作系统中的内存结构​ 在没有充分的理解函数集合是如何工作的以及它们各自是如何影响操作系统的情况下,在你的应用程序中确定用于管理内存的函数或函数集合是很困难的。下面重点介绍虚拟内存(Vir

2021-08-12 22:06:09 1030

原创 stack

stackstack的原则是先进后出,底层实现也是基于list进行实现。#ifndef TSTACK_H#define TSTACK_H#include <stdlib.h>#include <string.h>#include <list>#include <stack>using namespace std;template <class T>class TStack{public: TStack();

2021-08-11 21:41:51 96

原创 Linux下,writeread,recvsend, recvfromsendto的区别

Linux下,write/read,recv/send, recvfrom/sendto的区别先说概念和应用场景:read/wirte是通用的文件描述符操作;recv/send 通常应用于TCP;recvfrom/sendto通常应用于UDP。read/writessize_t write(int fd, const void*buf,size_t nbytes);ssize_t read(int fd,void *buf,size_t nbyte);​ write函数是将buf中的nbyt

2021-08-10 22:23:54 288

原创 C++ remove_reference(引用移除)

C++ remove_reference(引用移除)demo代码#include <iostream>using namespace std;int main(){ cout << "Hello World!" << endl; int val = 5; int& valRef = val; int& temp = valRef; valRef = 6; printf("valRef:%d

2021-06-04 21:28:01 4163

原创 linux 之 __thread & pthread_key_t

linux 之 __thread & pthread_key_t在说__thread之前,先来看看pthread_ket_t吧。参考:http://blog.csdn.net/lmh12506/article/details/8452700上面的博文说的比较通俗易懂。线程私有数据可以理解为线程内的全局变量。在线程内可以被所有函数访问,但是不能被其他线程的函数访问。对于pthread_key_t的使用,最好使用RAII://博主参照muduo写的#include <pthread.h&

2021-06-04 21:27:28 357

原创 Linux下pthread_once()函数

Linux下pthread_once()函数函数声明int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));1本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证*init_routine()*函数在本进程执行序列中仅执行一次。例子#include <semaphore.h>#include <sys/types.h>#include &lt

2021-06-04 21:27:03 161

原创 C++ 线程安全的单例模式总结

C++ 线程安全的单例模式总结什么是线程安全?在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。如何保证线程安全?给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。让线程也拥有资源,不用去共享进程中的资源。如: 使用threadlocal可以为每个线程的维护一个私有的本地变量。什么是单例模式?单例模式指在整个系统生命周期里,保证一个类只能产生一个实例,确保该类的唯一性。单例模式分类单例

2021-06-03 22:40:26 150

原创 引用、指针、普通类型的大小,以及相互转换的分析

引用、指针、普通类型的大小,以及相互转换的分析转换调用的函数​ 对象不存在,且没有用别的对象来初始化,就是调用了构造函数​ 对象不存在,且用别的对象来初始化,就是拷贝构造函数​ 对象存在,用别的对象来给他赋值,就是赋值函数。#include <iostream>using namespace std;class StructObj{public: StructObj() { a = 1; b = 2; }

2021-06-03 22:10:23 146

转载 C++中的mutable关键字

C++中的mutable关键字mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。我们知道,被const关键字修饰的函数的一个重要作用就是为了能够保护类中的成员变量。即:该函数可以使用类中的所有成员变量,但是不能修改他们的值。然而,在某些特殊情况下,我们还是需要在const函数中修改类的某些成员变量,因为要修改的成

2021-06-03 21:28:41 337

转载 C++ noncopyable原理及实现

C++ noncopyable原理及实现默认构造函数、拷贝控制成员以及它们的合成版本默认构造函数不含参数或者只含一个参数并且参数有默认值的构造函数。如果类没有定义任何构造函数,编译器会为其合成一个无参默认构造函数,也就是合成的默认构造函数。如果类定义了构造函数,编译器不会为其合成默认构造函数,也就不能执行默认初始化了,如:class A { int val; A(int v):val(v) {}};A a; //编译出错,没有默认构造函数可以指定编译器合成一个默认构

2021-06-03 21:13:19 237

转载 stdsame 与 typeid()

C++11的模板类型判断——std::is_same和std::decayC++11的模板类型判断——std::is_same和std::decay问题提出:有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是int型还是double型呢?如:#include <iostream>template<typename TYPE>void typeCheck(TYPE data){ //do someth

2021-06-03 20:49:39 236

转载 关于__builtin_expect

关于__builtin_expect先上代码 #include <stdio.h> #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) int main(int argc, const char* argv[]) { int count = 10; if (likely(count > 1)) print

2021-06-03 18:46:06 107

原创 自定义 C++atack

stackstack的原则是先进后出,底层实现也是基于list进行实现。#ifndef TSTACK_H#define TSTACK_H#include <stdlib.h>#include <string.h>#include <list>#include <stack>using namespace std;template <class T>class TStack{public: TStack();

2021-04-05 18:19:37 85

原创 自定义 C++ deque

deque双向队列,提供可以头部和尾部进行添加和删除元素的功能。最好的实现方案,就是指针数组,这样可以使用 下标进行元素访问以及添加删除元素。也可以理解list和vector的结合体。#ifndef TDEQUE_H#define TDEQUE_H#include <stdlib.h>#include <string.h>#include <ASSERT.H>using namespace std;template <class T>c

2021-04-05 18:18:34 215

原创 自定义 C++ queue

queue队列提供先进先出功能,从尾部添加元素,从头部取出元素。其实是基于list的功能进行封装#ifndef TQUEUE_H#define TQUEUE_H#include <stdlib.h>#include <string.h>#include <list>#include <queue>using namespace std;template <class T>class TQueue{public:

2021-04-05 18:15:49 373

原创 自定义 C++ map

mapmap底层的数据结构是红黑二叉树,他的优势是可以快速查找对象。key需要提供< 或者 >的操作符运算下面源码的红黑树是复制qt的QMap实现,当然也可以自己写红黑树实现。担心自己实现可能bug过多。tmap.h#ifndef TMAP_H#define TMAP_H#include <stdio.h>#include <string>template <class Key> inline bool mapLessThanKey(cons

2021-04-05 18:13:40 828

原创 自定义 C++ hash

散列表​ 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。​ hash表,本质是拿内存的空间换查找的时间,就是hash表的优势是查找的时间复杂度是比较稳定的。#ifndef THASH_H#define THASH_H#include <stdlib.h>#include <iterator&

2021-04-05 18:12:13 645

原创 自定义 C++ Vector

vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。因此能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内存拷贝。#ifndef TVECTOR_H#define TVECTOR_H#include <stdlib.h>#include <ASSERT.H>#include <string.h>

2021-04-05 17:52:52 744

原创 自定义实现 C++ list

c++的list为双向环形链表,优势在于可以快速插入删除任意节点,不能像vector通过下标快速访问元素。#ifndef TLIST_H#define TLIST_H#include <stdlib.h>#include <iterator>using namespace std;template <class T>class TList{private: struct node { T date; n

2021-04-05 17:50:59 796

原创 C++ 的标准库容器的实现

C++ 的标准库容器的实现listvectorforward_list二叉树与哈希表map二叉树与哈希表setdequequeuestack

2021-03-15 22:03:10 97

转载 红黑树与平衡二叉树的比较

RB-Tree和AVL树作为BBST,其实现的算法时间复杂度相同,AVL作为最先提出的BBST,貌似RB-tree实现的功能都可以用AVL树是代替,那么为什么还需要引入RB-Tree呢?红黑树不追求"完全平衡",即不像AVL那样要求节点的|balFact| <= 1,它只要求部分达到平衡,但是提出了为节点增加颜色,红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。 就.

2021-03-06 13:24:47 993

原创 R-B Tree

R-B Tree简介R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。红黑树的特性:(1)每个节点或者是黑色,或者是红色。(2)根节点是黑色。(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!](4)如果一个节点是红色的,则它的子节点必须是黑色的。(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。注

2021-03-06 12:56:06 129

原创 平衡二叉树

文章参考什么是平衡二叉树(AVL) 和 一步一步写平衡二叉树(AVL树)为什么要有平衡二叉树​ 二叉搜索树一定程度上可以提高搜索效率,但是当原序列有序时,例如序列 A = {1,2,3,4,5,6},构造二叉搜索树如图 1.1。依据此序列构造的二叉搜索树为右斜树,同时二叉树退化成单链表,搜索效率降低为 O(n)。在此二叉搜索树中查找元素 6 需要查找 6 次。​ 二叉搜索树的查找效率取决于树的高度,因此保持树的高度最小,即可保证树的查找效率。同样的序列 A,将其改为下图的方式存储,查找元素 6

2021-03-02 17:09:00 275

翻译 QT之D指针

什么是D指针如果你已经看过到Qt源码,你会发现它经常使用Q_D和Q_Q`宏。本文介绍了这些宏的用途。该Q_D和Q_Q宏是一个设计模式的一部分被称为d-指针(也称为*不透明的指针*,其中一个库的实现细节可以从它的用户,并转移到执行被隐藏),另外也保护了库的二进制兼容性。在设计类似Qt的库时,希望即使在将Qt库升级/替换为另一个版本之后,也可以继续运行动态链接到Qt的应用程序而无需重新编译。例如,如果您的应用程序CuteApp基于Qt 4.5,则应该能够将Qt库(在该应用程序附带的Windows上,在Li

2021-02-24 23:19:11 2600

原创 Linux下进程间通信方式——使用消息队列

Linux下进程间通信方式——使用消息队列一、什么是消息队列消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。二、在Linux中使用消息队列Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进

2021-01-23 14:53:23 113

原创 Linux下进程间通信方式——共享内存

Linux下进程间通信方式——共享内存1.什么是共享内存?共享内存就是允许两个或多个进程共享一定的存储区。就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。因为数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,所以这是最快的一种IPC。注:共享内存没有任何的同步与互斥机制,所以要使用信号量来实现对共享内存的存取的同步。共享内存特点和优势当中共享内存的大致原理相信我们可以看明白了,

2021-01-23 14:52:45 133

原创 Linux进程间通信——使用系统信号量

Linux进程间通信——使用系统信号量一、什么是信号量为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))

2021-01-23 14:51:41 135

原创 Linux进程间通信——使用POSIX信号量

Linux进程间通信——使用POSIX信号量一、引言信号量是包含一个非负整数型的变量,并且带有两个原子操作wait和signal。Wait还可以被称为down、P或lock,signal还可以被称为up、V、unlock或post。在UNIX的API中(POSIX标准)用的是wait和post。对于wait操作,如果信号量的非负整形变量S大于0,wait就将其减1,如果S等于0,wait就将调用线程阻塞;对于post操作,如果有线程在信号量上阻塞(此时S等于0),post就会解除对某个等待线程的阻塞,

2021-01-23 14:51:05 449

原创 Linux进程间通信之管道

Linux进程间通信之管道进程间通信 (IPC ) Inter-Process Communication比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。linux下IPC机制的分类​ 管道、信号、共享内存、消息队列、信号量、套接字特点管道是最古老的IPC,但目前很少使用以文件做交互的媒介,管道分为有名管道和无名管道历史上的管道通常是指半双工管道,如果需要双向通信,则创建两个管道3.2 管道:有两种形式,命令行和非命令行编程模型:进程A创建管道(mkfifo) -&

2021-01-23 14:50:35 67

原创 Posix 信号量与System v信号量的区别

Posix 信号量与System v信号量的区别在回答这个问题之前,首先要先了解什么是Posix,什么又是System V。简要的说,Posix是“可移植操作系统接口(Portable Operating System Interface )的首字母简写,但它并不是一个单一的标准,而是一个电气与电子工程学会即IEEE开发的一系列标准,它还是由ISO(国际标准化组织)和IEC(国际电工委员会)采纳的国际标准。而System v是Unix操作系统众多版本的一个分支,它最初是由AT&T在1983年第一

2021-01-23 14:49:58 445

原创 Linux中的各种锁及其基本原理

Linux中的各种锁及其基本原理0.概述通过本文将了解到如下内容:Linux系统的并行性特征互斥和同步机制Linux中常用锁的基本特性互斥锁和条件变量1.Linux的并行性特征Linux作为典型的多用户、多任务、抢占式内核调度的操作系统,为了提高并行处理能力,无论在内核层面还是在用户层面都需要特殊的机制来确保任务的正确性和系统的稳定运行,就如同一个国家需要各种法律条款来约束每个公民的行为,才能有条不紊地运转。在内核层面涉及到各种软硬件中断、进线程睡眠、抢占式内核调度、多处理器SMP架构

2021-01-23 14:49:18 1760

CMakeDemo.rar

windows 上使用cmake或者qtcreator创建C++多个子项目工程

2021-12-22

vld-2.5.1-setup.rar

visual leak detector ,安装包

2021-08-18

untitled9.rar

使用QT5进行实现的,支持多线程的Tcp服务端,线程使用movoToThread方式,并对各个客户端进行管理

2019-08-23

linux的tcp服务端与客户端demo源码

linux的非阻塞tcp非阻塞客户端和tcp非阻塞服务端demo 下载

2019-05-15

小甲鱼 OD使用教程registerMe.exe

供OD(Ollydbg)学习用的RegisterMe原版exe和Oops版exe

2019-05-05

C++与js相互调用

这里是 VC与JavaScript交互(三) ———— JS调用C++,下载的时候需要看清楚

2017-10-13

QT与JS的相互调用

m_pWebView->load(QUrl("file:///C:/Users/QGM/Desktop/QtInvokeJS/jsTest.html")); mainWindow.cpp的这句代码需要修改

2017-10-13

node.js+socket.io离线包+聊天室源码

这是基于socket.io实现双向实时通信的聊天室样例。来源于网上的博文,我对源码做了一些增强,并把需要的node.js、socket.io、jQuery、服务端和客户端源码,全部打在一起(node.js的npm需要在线安装,聊天室样例也有引用到互联网上的js文件,我把它们全部都本地化了,这样便于离线用户的测试,特别是我们公司这样不允许技术部电脑直接上网的)。 大家可以这样测试: 1、解压到某个 目录 2、点击运行start.bat,进入命令行环境 3、在命令行输入运行 node http.js 4、打开多个浏览器,分别访问http:\\localhost:8080,就可以看到效果

2017-10-13

学生管理系统

一个简单的学生管理系统,使用QT+Sqlite实现,视图使用tableview和Treeview,通过代理实现数据编辑,实时保存

2017-10-13

qml学习资料

最新版请从 https://github.com/cwc1987/QmlBook-In-Chinese下载

2017-10-13

qt打包工具

qt打包工具

2016-10-20

Struts的文件上传和下载

Struts的文件上传和下载

2016-09-05

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

TA关注的人

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