为什么C++没有Python那么多开源库?

2023-05-16


链接:https://www.zhihu.com/question/375368576/answer/1059898195

看了好多回答,还是觉得有更本质的原因的,根源还是在C++这个语言特性上

为什么C++没有Python之类语言这样活跃的生态?我觉得根本原因在于C++没有解决好一个问题:菱形依赖

什么叫菱形依赖呢?就是说A依赖B,A也依赖C,但是B和C同时依赖D,并且我们限定D并不是STL这样的标准库,BCD都是开源库。为了限定到C++,我们这里BCD都是C++库,采用源码的方式发布。

这种情况在生态活跃的语言中则是非常常见的。

在C++当中会怎样呢?

  1. B和C中至少一个将D的源码合并到了自己的源码里面,放到thirdparty之类的目录里面。A将两份源代码加自己的一起放到thirdparty里面,编译,符号冲突,爆炸
  2. B和C在install说明中提到,必须把依赖放到某个地方,然后修改Makefile/CMAKE/Bazel配置,将D的源码目录加进来。结果B和C编译出来的.a里面还是带着D的全部符号,A尝试二进制链接,符号冲突,爆炸
  3. B和C在install说明中提到,需要将D的依赖放在某个地方,先编译成.a,设置好参数直接链接.a。但是B和C要求的D的编译参数不一样,链接不到一起,爆炸
  4. 把所有的依赖都一个一个放在独立的位置上,设置好include目录,每个都用自己的Makefile独自编译成.a,编译参数用同一套,最后再一个一个指定起来链接到一起——人工成本爆炸
  5. A希望B和C通过动态链接方式连接,方便升级。动态链接库里面链接了D的符号,加载起来符号冲突,爆炸。B和C一个动态链接了D,一个静态链接了D,还是符号冲突,爆炸
  6. D把自己改成了header only的库,终于不需要单独编译了。B和C在引用D的时候设置的宏不一样,导致编译出的弱符号不兼容,链接完运行崩溃,爆炸

以上种种,最后对于C++库的作者来说,就变成了这样一个结果:

如果我要提供一个好用、好编译、不给我天天找事情的库,那么我不能引用其它的开源库

没有比这更矛盾的事情了,要造轮子,第一件事情是不能用别人的轮子。但是如果你要正经开发一个系统,你能保证自己不会有一天需要把这个代码重构成一个通用的库吗?那你就得从第一天开始避免用第三方开源库……

在Linux上面唯一有点生态的意思的做法,是引用yum/apt源里面的xxx-dev这样的库,这些库通过pkgconfig的方式组织,而且通过包管理系统保证大家下载到的都是相同且兼容而且编译好了的二进制库,引用起来很方便。但是,只有把接口限定到纯C才能发布确保二进制兼容的库,那折腾了半天,就算内部是C++开发的,一到库的边界上还得转成纯C,也就失去了C++语言的优势了。


只是没有一个集中的包管理系统(网站)而已,库都要自己找自己编译,哪像java一样,配置一下依赖就自动下载编译加入项目,或者py一样直接install就完了。现在c++的包管理,像vcpkg这样的,提供的库列表也不够全,有的还是要靠自己去找。而且由于c++的语言特性,就算是包管理自动下载的,可能也因为各种原因编译不过,还得自己去调整。
链接:https://www.zhihu.com/question/375368576/answer/1047465171


链接:https://www.zhihu.com/question/375368576/answer/1049057305

因为很多 C++程序员的口号就是:别人的东西都是不可靠的,信不过的,只要我精力和能力允许,用别人的还不如自己造,只有自己的才是最可靠的。因此从性格上就不倾向于协同,碎片严重。

而 Python 程序员的口号则是:有现成的用现成的,没现成的找现成的,找不到,我就不做了,因此从性格上倾向于协作。

很多 C++ 项目造轮子之心比 python 强很多,代码都没写三行,起手就是一个 BaseObject,要用我的库,必须继承我这个 BaseObject 或者 BaseTemplate,所有参数传递都要套一个 base::my_smartest_ptr 的劣质套套,再来一个 mini 基础库,定义一堆新的数据结构让你用。

人家就是来买你一根烤羊肉的,你就爱在你的烤肉串外面套一层 shit 强卖给人家,人家恐怕连你羊肉串都不想吃了。

Python 不会有这个情况,首先 py 基础库非常强大统一,不需要象 C++ 一样,项目稍微写大点都要发明半套基础库一样,成为新项目使用的障碍。Python 项目大部分就是专注解决 1-2 个痛点,不执着造轮子,不同的项目就容易在统一的基础库的语义下进行协同。

好点的 C++ 库是非侵入式的,比如把 API 封装成 C 的,全部用基础类型作为接口,这样内部你自己用成一朵花都没人管你,用 cffi 让脚本语言直接调用也比较方便。

因此从好恶上,前者更偏向于单枪匹马自己搞定一切,而后者更喜欢协同。


其实python的排名靠前的开源库核心部分都是c/c++的,python一直是一种便利的外壳语言,非常简单方便。现在大多c/c++模块也都愿意封装成python可调用模块之后使用,在python引入context之后更方便了,整个context内的代码可实现为全部被接管,看起来像python,或是可以python直接运行。其实实际上被接管之后后端可采用平台相关的各种优化库,CUDA,OPENCL,MPI之类的都可以。

​ 所在强烈建议使用纯python的去学习c/c++,可以极大拓展使用python的威力。而还没有接触python的c/c++的开发者学习python,可以极大增强现在工作流的便利性。

作者:saturnman
链接:https://www.zhihu.com/question/375368576/answer/1058324189
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


作者:nullptr
链接:https://www.zhihu.com/question/375368576/answer/1060186756
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

C++的库,或者说C++吧,很多东西可以算很依赖编译器、构建工具之类的版本、特性等等的了,"Header Only"的库好多也这样。

最简单的就是这样一种情况,源码全给你了,怎么编译都说了,也会有很多人编译半天都编译失败,就算是很熟练掌握那一套编译、链接过程的,有时候可能也要去稍微改一下库的源码,适配一下自己的环境。

然而你要是没搞好,报错就算了,要是你用的库模板多,那套娃式报错上来给你来几十条几百条,要是写库的人写飞了什么指针,那错误定位也是麻烦得很…

良心的库,会针对各个主流平台做测试、适配,比如LLVM,每次release那一堆,但很多库作者是大佬中的大佬,他觉得这些东西都挺简单的,我核心思想都给你了,你应该一点通啊,自己写一个都可以了。

而且C++范式多,C++的开发者也都在自己吵,都觉得自己的范式是对的,这样库的特异性就更高了。

Python的库,因为python这一类语言的特点,本身社区就比较统一,绝大部分的库都是直接拿过来import就可以了,尽管很多底层可能是C++来做的,但毕竟有大佬给套壳了,这样使用门槛大大降低,所以感觉上python开源库就特别多。

(我觉得C++的库还算挺多的…就是拿来即用的可能是真的不多…)


大家都说的很全了, 还有一点没人提.

C/C++ 自由度太大, 引入一个垃圾库, 风险太大.

万一有个逗比指针飞了, 你怎么从 50+ 个依赖里找到谁是有问题的…

带 VM / 胖 runtime 的语言总有兜底. C++ 是直接炸穿.

写 C++ 代码就像做外科手术, 每一行代码都很厚重的…

一些久经考验的库, 比如 gflags, gtest, 用的还是非常广泛的.

作者:林谨
链接:https://www.zhihu.com/question/375368576/answer/1058412374
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


作者:机器学习入坑者
链接:https://www.zhihu.com/question/375368576/answer/1049634508
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

*C++开源库*:

菜鸟和大神都不会用,菜鸟不会用是因为不懂,大神不会用是因为不屑。菜鸟无奈转行学python,大神们开始用C++写开源库,然后成为业界标准。

*python开源库:*

python只需要7天就从入门到精通了,所以全部都是大神。一部分大神开始调包之旅,另一部分大神转回C/C++,目的是为了用C++写python的库,毕竟numpy、tensorflow、pytorch这些比较火热的python库都是C++写的,速度快。

综上,所有编程的人都是大神,python大神喜欢调库,C++大神喜欢写库

分割线


不开玩笑了,说点正事

*从使用角度看:*

python语法简单,开源库只要功能强大,必然在整个社区迅速流行,而且可以嵌入到自己的项目中,省时省力还安全。

但是,C++的开源库即使功能强大,在社区迅速流行的难度仍然非常大,尤其是对新人来说,使用开源库要知道:*指针、引用、函数指针、指针函数、数组指针、指针数组、常成员、静态成员、多态、模板等等,加上C++较为复杂的符号“::、&、*、<>、.、->”*等等,使用开源库对大部分新人来说实在太不友好了。

*从“源码可读性”角度看:*

代码出问题时,经常需要查库的源码。python库的源码基本上难点就在于逻辑结构,只要对算法的思路清晰,阅读很顺畅。但是,阅读C++库的源码时完全不仅要搞清楚逻辑结构,还要考虑内存释放、指针的安全性等一系列问题,难度比python大很多。

总结

从我的角度,我还是喜欢C++多一点,因为C++更接近底层,长时间使用C++能加强我对编程整体的把握。我用python写代码的时候,很少考虑“空间复杂度”和“时间复杂度”的问题,目的就是尽快实现预期功能;我用C++写代码的时候,能不能实现预期功能都是次要的,关键是代码的安全性和效率性必须要高,否则重构代码非常困难,至于预期功能完全可以顺势下调。

对了,七天学会python指的是“学会调库”,而不是“学会写算法”。我从大四开始,到研一中期才具备一定的自己写算法的能力,而且很菜。


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

为什么C++没有Python那么多开源库? 的相关文章

随机推荐

  • astra 深度相机 + orbslam2 ~ 稠密建图

    在ROS下运行ORB SLAM2 主要包括以下几步 xff1a 一 创建ROS工作空间 二 下载usb cam xff08 单目相机驱动包 xff09 三 下载深度相机驱动包 四 下载ORB SLAM2稠密建图代码 五 运行 一 创建ROS
  • Java字符串的处理

    文章目录 本章学习要点 Java定义字符串 xff08 2种方式 xff09 直接定义字符串例 1 使用 String 类定义1 String 2 String String original 3 String char value 4 S
  • Java数字和日期处理:Java数字处理和日期类

    文章目录 本章学习要点 Java Math类的常用方法静态常量例 1 求最大值 最小值和绝对值例 2 求整运算例 3 三角函数运算例 4 指数运算例 5 Java生成随机数 xff08 random 和Random类 xff09 例 1例
  • Java内置的包装类

    文章目录 本章学习要点 Java包装类 装箱和拆箱装箱和拆箱包装类的应用1 实现 int 和 Integer 的相互转换2 将字符串转换为数值类型3 将整数转换为字符串 Java Object类详解toString 方法equals 方法例
  • Java输入/输出(I/O)流

    文章目录 本章学习要点 Java流是什么 xff1f 输入 输出流又是什么 xff1f 什么是输入 输出流输入流输出流 Java系统流例 1 Java字符编码介绍Java File类 xff08 文件操作类 xff09 详解获取文件属性例
  • Java异常处理

    文章目录 本章学习要点 Java异常 xff08 Exception xff09 处理及常见异常异常简介例 1 异常类型 Java中Error和Exception的异同例 1 Java异常处理机制及异常处理的基本结构Java try cat
  • Java注解

    文章目录 本章学习要点 Java注解 xff08 Annotation xff09 简介Java 64 Override注解Java 64 Deprecated注解Java 64 SuppressWarnings xff1a 抑制编译器警告
  • 如何夸人?

    文章目录 夸人要怎么夸到心坎上 xff1f 01 有理有据 xff0c 细节见诚意02 一如既往保持信任与支持03 由表及里 xff0c 夸TA前先夸自己04 先抑后扬 xff0c 对比式夸奖05 创造条件引导TA自夸 如何做一只舔狗 xf
  • Java继承和多态

    文章目录 本章学习要点 Java类的封装例 1 Java封装图书信息类Java继承 xff08 extends xff09 简明教程例 1 单继承继承的优缺点 Java super关键字详解super调用父类构造方法例1例2 super访问
  • java中接口(interface)详解

    分享记录一下java接口的博客 xff1a java中接口 xff08 interface xff09 详解 JAVA基础 接口 xff08 全网最详细教程 xff09
  • java引用详解

    文章目录 一 关于对象与引用之间的一些基本概念 new Vehicle Vehicle veh1二 Java对象及引用三 只有理解了对象和引用的关系 xff0c 才能理解参数传递总结 xff1a 什么是值传递 xff0c 什么是引用传递 为
  • python学习-def __init__(self)理解(1)

    python中 init 的作用 在python中创建类后 xff0c 通常会创建一个 init 方法 xff0c 这个方法会在创建类的实例的时候自动执行 实例1 实例化Bob这个对象的时候 xff0c init 方法会自动执行 xff1a
  • 学完java基础语法之后用来练习的不依赖框架的小项目

    刚学完一门语言基础语法之后 xff0c 一般都需要写一些小项目来检验我们的学习效果 xff0c 将所学的基础语法串联起来 xff0c 同时也熟悉一下用这门语言做项目的大概流程 但是此时学习的项目不能太复杂 xff0c 因此此时才刚学完基础语
  • java集合中接口和类的理

    一 背景 首先我们可以先了解一下类和接口的基础和使用方法 xff1a Java类和对象 java中接口 xff08 interface xff09 详解 Java继承和多态 然后再对java集合的基础了解一下 Java集合 泛型和枚举 有了
  • java多线程详解

    文章目录 多线程基础进程进程 vs 线程多线程 创建新线程线程的优先级练习小结 线程的状态小结 中断线程小结 守护线程练习小结 线程同步不需要synchronized的操作小结 同步方法小结 死锁死锁练习小结 转载于 xff1a https
  • Java项目管理工具Maven使用方法详解

    这边直接推荐两个比较好的教程 xff1a https www liaoxuefeng com wiki 1252599548343744 1309301178105890 http c biancheng net maven2 depend
  • maven引入依赖包,import依赖包,编译运行maven项目

    文章目录 IDEA中新建一个maven项目在pom xml中添加依赖包 xff0c 确定依赖包成功导入 xff0c 在项目中import依赖包怎么确定maven成功的导入了依赖包在项目中import导入的依赖包总结 在看这篇博客之前 xff
  • 怎样做一个好的PPT演讲

    文章目录 一 做好PPT演讲的重要性二 怎么做好PPT演讲1 做一个好的PPT2 做好演讲 三 分析一些比较好的PPT演讲视频四 实例解析和总结 一 做好PPT演讲的重要性 不管是在学生时期的竞赛展示 xff0c 毕业答辩 xff0c 我们
  • PPT怎么画出好看的三维示意图

    一 前言 之前一些博客已经大致讲了PPT怎么画图的 xff1a PPT画图文章总结 怎样做一个好的PPT演讲 其实对于我们平常在PPT中会出现的图片 xff0c 可以简单的分为二维示意图和三维示意图 xff0c 二维示意图制作起来相对简单
  • 为什么C++没有Python那么多开源库?

    链接 xff1a https www zhihu com question 375368576 answer 1059898195 看了好多回答 xff0c 还是觉得有更本质的原因的 xff0c 根源还是在C 43 43 这个语言特性上 为