zoukankan      html  css  js  c++  java
  • boost库的安装,使用,介绍,库分类

    1)首先去官网下载boost源码安装包:http://www.boost.org/

            选择下载对应的boost源码包。本次下载使用的是 boost_1_60_0.tar.gz 

    (2)解压文件:tar -zxvf boost_1_60_0.tar.gz 

    (3)进入源代码路径执行命令  ./bootstrap.sh

            这一条命令完成boost默认配置,当然编译boost是需要gcc 和 g++的支持的。如果没有gcc 和 g++可以执行命令:

            yum install gcc gcc-c++  安装gcc g++

           这一条命令默认的安装路径配置为/usr/local/路径下。及执行这条命令等同执行以下命令

            ./bootstrap.sh –prefix=/usr/local/

         也就是默认的boost头文件安装到/usr/local/include/文件夹下。boost库文件会安装到/usr/local/lib/文件夹下。安装完成之后      你会在对应的文件夹下看到对应的文件。 

    (4)执行完上一条命令之后可以执行命令  ./b2  进行编译。(注意:编译需要耗费相当长的一段时间) 

    (5)然后执行下面安装命令 

            ./b2 install  或者 ./bjam install

           安装命令应该是管理员权限,因为需要到向系统中拷贝文件及库文件。 

    (6)将/usr/local/include下的boost文件夹及里面的内容全部拷贝到/usr/include/下。

    将/usr/local/lib下的所有文件拷贝到/usr/lib下。 

    (7)测试test.cpp 

    [cpp] view plain copy 
     
     print?在CODE上查看代码片派生到我的代码片
    1. #include <boost/thread.hpp>   
    2. #include <iostream>   
    3.      
    4. void task1() {    
    5.     // do stuff   
    6.     std::cout << "This is task1!" << std::endl;   
    7. }   
    8.      
    9. void task2() {    
    10.     // do stuff   
    11.     std::cout << "This is task2!" << std::endl;   
    12. }   
    13.      
    14. int main (int argc, char ** argv) {   
    15.     using namespace boost;    
    16.     thread thread_1 = thread(task1);   
    17.     thread thread_2 = thread(task2);   
    18.      
    19.     // do other stuff   
    20.     thread_2.join();   
    21.     thread_1.join();   
    22.     return 0;   
    23. }   

    编译指令: g++ test.cpp -o test -lboost_thread  

    3.设置环境变量
            在/etc/profile.d新建可执行文件boost.sh,添加文件内容:

    #!/bin/sh
    BOOST_INCLUDE=/home/boost-1.56.0/sdk/include/boost 
    BOOST_LIB==/home/boost-1.56.0/sdk/lib
    export BOOST_INCLUDE BOOST_LIB 

    命令行执行:source /etc/profile.d/boost.sh
            以后在编译程序时,只需要用:-I$BOOST_INCLUDE -L$BOOST_LIB 即可,还要使用-l指定了链接库。

    然后, /etc/ld.so.conf 文件添加so库的环境变量 /home/boost-1.56.0/sdk/lib(主要关键问题)

    修改完成后,通过ldconfig命令进行重启 

      (5).编译完成后,在/usr/local/include/boost目录中就有了新的boost头文件,在/usr/local/lib目录中就会有编译好的.so库文件和.a库文件。

      (6).进入/etc/ld.so.conf.d/目录,创建boost.conf文件,并写入/usr/local/lib/然后保存退出。然后输入命令:ldconfig重新加载所有库。执行完成后可以输入:ldconfig -v | grep boost命令来查看最新编译好的库是否已经加载。如果没有加载则可能上面的几个步骤有缺失或者执行出错。

      注意:做以上所有操作时,必须要root权限,否则会安装失败。

     vi ~/.bash_profile

    最后加入

    export boost='
    -lboost_date_time
    -lboost_filesystem
    -lboost_graph
    -lboost_iostreams
    -lboost_math_c99
    -lboost_math_c99f
    -lboost_math_c99l
    -lboost_math_tr1
    -lboost_math_tr1f
    -lboost_math_tr1l
    -lboost_prg_exec_monitor
    -lboost_program_options
    -lboost_python
    -lboost_regex
    -lboost_serialization
    -lboost_signals
    -lboost_system
    -lboost_unit_test_framework
    -lboost_wave
    -lboost_wserialization'
    以后编译就可以使用g++ xxx.cpp $boost即可。

    在线教程: http://boost.ez2learn.com/libs/libraries.htm

    document: http://www.boost.org/doc/libs/1_61_0/

     
    Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一。 Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。Boost由于其对跨平台的强调,对标准C++的强调,与编写平台无关。大部分boost库功能的使用只需包括相应头文件即可,少数(如正则表达式库,文件系统库等)需要链接库。但Boost中也有很多是实验性质的东西,在实际的开发中实用需要谨慎。
    Boost库是为C++语言标准库提供扩展的一些C++程序库的总称。
    Boost库由Boost社区组织开发、维护。其目的是为C++程序员提供免费、同行审查的、可移植的程序库。Boost库可以与C++标准库完美共同工作,并且为其提供扩展功能。Boost库使用Boost License来授权使用。
    Boost社区建立的初衷之一就是为C++的标准化工作提供可供参考的实现,Boost社区的发起人Dawes本人就是C++标准委员会的成员之一。在Boost库的开发中,Boost社区也在这个方向上取得了丰硕的成果。在送审的C++标准库TR1中,有十个Boost库成为标准库的候选方案。在更新的TR2中,有更多的Boost库被加入到其中。从某种意义上来讲,Boost库成为具有实践意义的准标准库。
    可下载Boost C++ Libraries安装boost库。大部分boost库功能的使用只需包括相应头文件即可,少数(如正则表达式库,文件系统库等)需要链接库。里面有许多具有工业强度的库,如graph库。
     
     
     
    按照实现的功能,Boost可为大致归入以下20个分类,在下面的分类中,有些库同时归入几种类别。

    字符串和文本处理库

    a) Conversion库:对C++类型转换的增强,提供更强的类型安全转换、更高效的类型安全保护、进行范围检查的数值转换和词法转换。
    b) Format库:实现类似printf的格式化对象,可以把参数格式化到一个字符串,而且是完全类型安全的。
    c) IOStream库 :扩展C++标准库流处理,建立一个流处理框架。
    d) Lexical Cast库:用于字符串、整数、浮点数的字面转换。
    e) Regex 库:正则表达式,已经被TR1所接受。
    f) Spirit库:基于EBNF范式的LL解析器框架
    g) String Algo库:一组与字符串相关的算法
    h) Tokenizer库:把字符串拆成一组记号的方法
    i) Wave库:使用spirit库开发的一个完全符合C/C++标准的预处理器
    j) Xpressive 库:无需编译即可使用的正则表达式

    容器库

    a) Array 库:对C语言风格的数组进行包装
    b) Bimap 库:双向映射结构库
    c) Circular Buffer 库:实现循环缓冲区的数据结构
    d) Disjoint Sets库 :实现不相交集的库
    e) Dynamic Bitset 库:支持运行时调整容器大小的位集合
    f) GIL 库:通用图像库
    g) Graph 库:处理图结构的库
    h) ICL 库:区间容器库,处理区间集合和映射
    i) Intrusive 库:侵入式容器和算法
    j) Multi-Array 库:多维容器
    k) Multi-Index 库:实现具有多个STL兼容索引的容器
    l) Pointer Container 库:容纳指针的容器
    m) Property Map 库:提供键/值映射的属性概念定义
    n) Property Tree 库:保存了多个属性值的树形数据结构
    o) Unordered 库:散列容器,相当于hash_xxx
    p) Variant 库:简单地说,就是持有string, vector等复杂类型的联合体

    迭代器库

    a) GIL 库:通用图像库
    b) Graph 库:处理图结构的库
    c) Iterators 库:为创建新的迭代器提供框架
    d) Operators 库:允许用户在自己的类里仅定义少量的操作符,就可方便地自动生成其他操作符重载,而且保证正确的语义实现
    e) Tokenizer 库:把字符串拆成一组记号的方法

    算法库

    a) Foreach库:容器遍历算法
    b) GIL库:通用图像库
    c) Graph库:处理图结构的库
    d) Min-Max库:可在同一次操作中同时得到最大值和最小值
    e) Range库:一组关于范围的概念和实用程序
    f) String Algo库:可在不使用正则表达式的情况下处理大多数字符串相关算法操作
    g) Utility库:小工具的集合

    函数对象和高阶编程库

    a) Bind库:绑定器的泛化,已被收入TR1
    b) Function库:实现一个通用的回调机制,已被收入TR1
    c) Functional库:适配器的增强版本
    d) Functional/Factory库:用于实现静态和动态的工厂模式
    e) Functional/Forward库:用于接受任何类型的参数
    f) Functional/Hash库:实现了TR1中的散列函数
    g) Lambda库:Lambda表达式,即未命名函数
    h) Member Function库:是STL中mem_fun和mem_fun_ref的扩展
    i) Ref库:包装了对一个对象的引用,已被收入TR1
    j) Result Of库:用于确定一个调用表达式的返回类型,已被收入TR1
    k) Signals库:实现线程安全的观察者模式
    l) Signals2库:基于Signal的另一种实现
    m) Utility库:小工具的集合
    n) Phoenix库:实现在C++中的函数式编程

    泛型编程库

    a) Call Traits库:封装可能是最好的函数传参方式
    b) Concept Check库:用来检查是否符合某个概念
    c) Enable If库:允许模板函数或模板类在偏特化时仅针对某些特定类型有效
    d) Function Types库:提供对函数、函数指针、函数引用和成员指针等类型进行分类分解和合成的功能
    e) GIL库:通用图像库
    f) In Place Factory, Typed In Place Factory库:工厂模式的一种实现
    g) Operators库:允许用户在自己的类里仅定义少量的操作符,就可方便地自动生成其他操作符重载,而且保证正确的语义实现
    h) Property Map库:提供键值映射的属性概念定义
    i) Static Assert库:把断言的诊断时刻由运行期提前到编译期,让编译器检查可能发生的错误
    j) Type Traits库:在编译时确定类型是否具有某些特征
    k) TTI库:实现类型萃取的反射功能。

    模板元编程

    a) Fusion库:提供基于tuple的编译期容器和算法
    b) MPL库:模板元编程框架
    c) Proto库:构建专用领域嵌入式语言
    d) Static Assert库:把断言的诊断时刻由运行期提前到编译期,让编译器检查可能发生的错误
    e) Type Traits库:在编译时确定类型是否具有某些特征

    预处理元编程库

    a) Preprocessors库:提供预处理元编程工具

    并发编程库

    a) Asio库:基于操作系统提供的异步机制,采用前摄设计模式实现了可移植的异步IO操作
    b) Interprocess库:实现了可移植的进程间通信功能,包括共享内存内存映射文件信号量文件锁消息队列
    c) MPI库:用于高性能的分布式并行开发
    d) Thread库:为C++增加线程处理能力,支持Windows和POSIX线程
    e) Context库:提供了在单个线程上的协同式多任务处理的支持。该库可以用于实现用户级的多任务处理的机制,比如说协程coroutines,用户级协作线程或者类似于C#语言中yield关键字的实现。[1] 
    f) Atomic库:实现C++11样式的atomic<>,提供原子数据类型的支持和对这些原子类型的原子操作的支持。
    g)Coroutine库:实现对协程的支持。协程与线程的不同之处在于,协程是基于合作式多任务的,而多线程是基于抢先式多任务的。
    h)Lockfree库:提供对无锁数据结构的支持。

    数学和数字库

    a) Accumulators库:用于增量计算的累加器的框架
    b) Integer库:提供一组有关整数处理的类
    c) Interval库:处理区间概念的数学问题
    d) Math库:数学领域的模板类和算法
    e) Math Common Factor库:用于支持最大公约数和最小公倍数
    f) Math Octonion库 :用于支持八元数
    g) Math Quaternion库:用于支持四元数
    h) Math/Special Functions库:数学上一些常用的函数
    i) Math/Statistical Distributions库:用于单变量统计分布操作
    j) Multi-Array库:多维容器
    k) Numeric Conversion库:用于安全数字转换的一组函数
    l) Operators库:允许用户在自己的类里仅定义少量的操作符,就可方便地自动生成其他操作符重载,而且保证正确的语义实现
    m) Random库:专注于伪随机数的实现,有多种算法可以产生高质量的伪随机数
    n) Rational库:实现了没有精度损失的有理数
    o) uBLAS库:用于线性代数领域的数学库
    p) Geometry库:用于解决几何问题的概念、原语和算法。
    q) Ratio库:根据C++ 0x标准N2661号建议[2]  ,实现编译期的分数操作。
    r)Multiprecision库:提供比C++内置的整数、分数和浮点数精度更高的多精度数值运算功能。[3] 
    s)Odeint库:用于求解常微分方程的初值问题。[4] 

    排错和测试库

    a) Concept Check库 :用来检查是否符合某个概念
    b) Static Assert库 :把断言的诊断时刻由运行期提前到编译期,让编译器检查可能发生的错误
    c) Test库:提供了一个用于单元测试的基于命令行界面的测试套件

    数据结构库

    a) Any库:支持对任意类型的值进行类型安全的存取
    b) Bimap库:双向映射结构库
    c) Compressed Pair库:优化的对pair对象的存储
    d) Fusion库:提供基于tuple的编译期容器和算法
    e) ICL库:区间容器库,处理区间集合和映射
    f) Multi-Index库:为底层的容器提供多个索引
    g) Pointer Container库:容纳指针的容器
    h) Property Tree库:保存了多个属性值的树形数据结构
    i) Tuple库:元组,已被TR1接受
    j) Uuid库:用于表示和生成UUID
    k) Variant库:有类别的泛型联合类
    l) Heap库:对std::priority_queue扩展,实现优先级队列
    m) Type Erasure: 实现运行时的多态。

    图像处理库

    a) GIL库:通用图像库

    输入输出库

    a) Assign库:用简洁的语法实现对STL容器赋值或者初始化
    b) Format库:实现类似printf的格式化对象,可以把参数格式化到一个字符串,而且是完全类型安全的
    c) IO State Savers库:用来保存流的当前状态,自动恢复流的状态等
    d) IOStreams库:扩展C++标准库流处理,建立一个流处理框架
    e) Program Options库:提供强大的命令行参数处理功能
    f) Serialization库:实现C++数据结构的持久化

    跨语言混合编程库

    a) Python库:用于实现Python和C++对象的无缝接口和混合编程

    内存管理库

    a) Pool库:基于简单分隔存储思想实现了一个快速、紧凑的内存池库
    b) Smart Ptr库:智能指针
    c) Utility库:小工具的集合

    解析库

    a) Spirit库:基于EBNF范式的LL解析器框架

    编程接口库

    a) Function库:实现一个通用的回调机制,已被收入TR1
    b) Parameter库:提供使用参数名来指定函数参数的机制

    综合类库

    a) Compressed Pair库:优化的对pair对象的存储
    b) CRC库:实现了循环冗余校验码功能
    c) Date Time 库:一个非常全面灵活的日期时间库
    d) Exception库:针对标准库中异常类的缺陷进行强化,提供<<操作符重载,可以向异常传入任意数据
    e) Filesystem库:可移植的文件系统操作库,可以跨平台操作目录、文件,已被TR2接受
    f) Flyweight 库:实现享元模式,享元对象不可修改,只能赋值
    g) Lexical Cast 库:用于字符串、整数、浮点数的字面转换
    h) Meta State Machine库:用于表示UML2有限状态机的库
    i) Numeric Conversion 库:用于安全数字转换的一组函数
    j) Optional 库:使用容器的语义,包装了可能产生无效值的对象,实现了未初始化的概念
    k) Polygon 库:处理平面多边形的一些算法
    l) Program Options库:提供强大的命令行参数处理功能
    m) Scope Exit库:使用preprocessor库的预处理技术实现在退出作用域时资源自动释放
    n) Statechart库:提供有限自动状态机框架
    o) Swap库:为交换两个变量的值提供便捷方法
    p) System库:使用轻量级的对象封装操作系统底层的错误代码和错误信息,已被TR2接受
    q) Timer库:提供简易的度量时间和进度显示功能,可以用于性能测试等需要计时的任务
    r) Tribool库:三态布尔逻辑值,在true和false之外引入indeterminate不确定状态
    s) Typeof库:模拟C++0x新增加的typeof和auto关键字,以减轻变量类型声明的工作,简化代码
    t) Units库:实现了物理学的量纲处理
    u) Utility库:小工具集合
    v) Value Initialized库:用于保证变量在声明时被正确初始化
    w) Chrono库:实现了C++ 0x标准中N2661号建议[2]  所支持的时间功能。
    x) Log库:实现日志功能。
    y) Predef库:提供一批统一兼容探测其他宏的预定义宏。[5] 

    编译器问题的变通方案库

    a) Compatibility库:为不符合标准库要求的环境提供帮助
    b) Config库:将程序的编译配置分解为三个部分:平台、编译器和标准库,帮助库开发者解决特定平台特定编译器的兼容问题
     
     
     
     
    Boost中比较有名气的有这么几个库:
    Regex
    正则表达式库
    Spirit
    LL parser framework,用C++代码直接表达EBNF
    Graph
    图组件和算法
    Lambda
    在调用的地方定义短小匿名的函数对象,很实用的functional功能
    concept check
    检查泛型编程中的concept
    Mpl
    用模板实现的元编程框架
    Thread
    可移植的C++多线程库
    Python
    把C++类和函数映射到Python之中
    Pool
    内存池管理
    smart_ptr
    5个智能指针,学习智能指针必读,一份不错的参考是来自CUJ的文章:

    Boost的部分内容已经进入C++ 11 标准,那么直接在网上查C++的文档资料就可以了,比如或者
    对于不是标准的部分,直接看官方文档就可以了。

    我最近也在学boost,说一点自己的建议和经历

    boost内容比较多,除了之前有人说过的一些已经成为C++标准的东西以外还有很多其他的组件,像graph啊math啊GIL这样专业性很强的,也有一些很好用的小组件比如说时间日期,filesystem 这样的,可以根据自己需要有选择的学习

    英文水平好的话建议直接看文档,觉得文档没讲清楚的可以谷歌找点例子(我在学GIL的时候发现boost官方少了文件(关于图像缩放的),而GIL是当初Adobe捐出来的,其官方的相关页面早已挂,谷歌了半天才在一个svn上找到……)

    书的话国内的倒是有罗剑锋写的《Boost程序库完全开发指南》和《Boost程序库探秘》,前者是一个大体的介绍,后者是针对一些诸如模板元编程等高级特性做了深入的探讨。两本我都有,感觉写的不错,目前正在学习。

    国外的只看过《Boost C++ Application Development Cookbook》国内有翻译的,也只是对boost做了一个大概的介绍,感觉一般不是很推荐。



    学习C++有没有必要学习boost库?

    1.【boost有没有用】在哪些情形下STL不够用,需要用到boost,否则就要自己造轮子?这样的情形多不多?会boost之后和其他不会boost的程序员相比有哪些优势?
    2.【boost能不能用】在使用C++开发项目的公司里boost库普及情况如何?公司一般允许不允许使用boost库?开源项目用boost的多不多?
    3.【boost好不好用】使用boost库的程序是否易于调试?boost库效率如何?在多线程等环境下使用是否安全?
    4.【boost好不好学】boost库学习难度如何?应该先深入学习C++再学boost还是掌握C++基本语法就学boost?应该学习boost的全部还是一些重要的部分?
    5.boost库的发展前景如何?
     
    1.不支持C++11的编译器, boost 库里面最值得使用的是 bind,function,shared_ptr等,这些东西运用好会让代码非常漂亮而且不用担心内存泄漏问题
    2.boost库之前的公司中项目用了boost很多东西,陈硕的muduo库中也用了boost的东西,性能问题不需要担心,而且写代码会舒服很多
    3.boost性能不需要担心,调试不好调,因为根本看不懂,特别是bind function这块,基本你要看错误直接一眼就看出来问题不太可能,需要熟练使用后根据经验才知道是哪里有问题.多线程使用问题和你代码设计有关系和boost没关系
    4.boost难度不算大,看源码会很费劲,只要会用即可,基本上用的多的就那么几个
    5.boost 在VS 2013(/2012),gcc 4.8之前可以说离开了boost会很不爽,但是之后boost里面用的就相对少了,因为很多糖都是从boost高过去的,不过boost的asio还是可以使用下,好用,舒服,性能足够用.

    boost 很有必要学习。boost 有很多好用的组件,可以作为基本积木块来构建自己的项目。这样随手就用,不用自己花费很多时间精力去土法练钢,还只练出个铁渣。比如 noncopyable、字符串算法、format、pool、xpressive、flat_map 等等都是很实用的。function,bind,lambda, shared_ptr,auto 等已经进入 C++ 11,用 boost 已经没有必要了。

    boost 的性能不需要担心。

    boost 唯一的问题包含太多的东西(这个是它优点也是缺点),太庞大了,直接包含到工程中不方便。

    实际应用中,我都是将 boost 库下载后放在本机的某个地方,之后建立一个 /boost 符号链接指向实际的路径。就这样在本机中配置一次,全部工程都可以用 boost 库了。项目组的成员也就做一次,也不算麻烦。boost 库的具体普及情况我不清楚,至少我之前的公司是可以使用的。

    boost 很多库都可以直接包含头文件就可以使用。而一些库需要编译,但分平台编译比较麻烦,建议建立一个 boost_pre_build.cpp 文件,将一些需要编译的 boost cpp文件直接包含进去。比如

    // boost_pre_build.cpp
    #include <libs/system/src/error_code.cpp>
    

    包含太多的 cpp 文件,符号可以会冲突,就多建一个 boost_pre_build_1.cpp,将一些 boost cpp 分开。这样做虽然粗暴,但比自己去折腾编译要省很多时间。比如需要在 iOS 项目中使用。

    很多 boost 库采用 STL 的风格,需要 STL 的基础。建议先用好 STL 再去看 boost。

    boost 太庞杂。boost 更准确的说,并不是一个库,而是一个库集合。不用每个都去看。应该先快速翻阅一些简介,只需要了解一下有什么库,每个库大概是做什么东西的。之后碰到问题再细看具体的库用法。应该直接使用,千万千万不要去分析它的源码,那个是无底洞。

     
    要用的时候再用,项目的依赖当然是越少越好了。
    我用boost主要有两个用途:
    1. 真的需要,比如bimap这种奇怪的数据结构
    2. 试图去理解 stl。boost里面的代码可比自带的stl清晰多了,我精简了unique_ptr的代码,现在平时记不住它的接口功能,就翻翻我的精简版实现,毕竟对于短实现show me the codes远远比talk more要好用。


    问题太多太难回答,我就说说主观看法
    1、有用,STL还是很有限,你光看boost的组件列表也知道比STL多太多内容了。我建议你问问题之前还是得了解一下两者到底能做什么。
    2、基本能用,能不能用完全看项目需求和有关负责人决策。例如服务器程序可能会采用,嵌入式设备就会拒绝。
    3、不好说。不算难调试,不过也不算好调试。效率倒是可以,不过要是用的组件多了,再加上相互依赖,boost本身的空间占用都会是个问题。安不安全请阅读接口文档,会告诉你是不是线程安全的。
    4、看你想学到哪,内容很多,如果只是拿来用用不在乎里面的设计,那倒容易。请先学好C++。学多少还是看需求。
    5、还行,基本是C++新特性的试验场,以前发明的很多东西都被纳入新C++标准(C++11,C++14)


    java用起来为什么那么爽 语法简单啊 更爽的是各种库都有拿来就能用啊 
    华山论剑 最悲哀的是什么 是不会爬山啊 java的下好的库 还没听说谁不会编译的
    win的c++程序员下个代码发现是linux平台的 顿时泪流满面 各种臣妾做不到啊 
    其实 即使是下载个别的win程序员写的代码 也不见得编译的过去啊 
    boost啊 不用担心编译问题 不用担心跨平台问题 也不用担心不够强大的问题 
    c++11的一些新特性就学的boost C++14的新特性也会是
    轻松加愉快的方式敲代码 干嘛要跟自己过不去呢



     
     
  • 相关阅读:
    [转] JavaScript中的字符串操作
    关于多线程学习的笔记
    [转] jquery 使用方法
    ubuntu下安装tomcat和配置mysql
    [转] 使用CodeViz生成C/C++函数调用关系图
    [转] java中的匿名内部类总结
    [转] Java中继承thread类与实现Runnable接口的区别
    字符串 指针、调试---师傅传授 栈中指针地址 与 堆中数据地址 标准写法
    maven 阿里云节点,速度快
    解决IntelliJ IDEA 创建Maven项目速度慢问题 DarchetypeCatalog
  • 原文地址:https://www.cnblogs.com/timssd/p/5544567.html
Copyright © 2011-2022 走看看