找回密码
 立即注册
查看: 212|回复: 5

为什么c/c++没有反射?

[复制链接]
发表于 2023-8-22 17:01 | 显示全部楼层 |阅读模式
在Java和golang中都是存在反射的,而为什么c或者c++没有反射机制?有大佬给个详细的解答吗?
发表于 2023-8-22 17:02 | 显示全部楼层
C/C++没有内置的反射机制是因为这些语言注重编译时效率和运行时性能,而反射需要在运行时对程序进行动态分析和调用,会增加运行时开销。此外,C/C++也没有面向对象语言如Java和C#那样强调反射概念的重要性。然而,C/C++可以通过手动实现一些类似于反射的机制,如函数指针、宏定义等来实现动态调用。
发表于 2023-8-22 17:03 | 显示全部楼层
不管 C,我来单独说说 C++吧。
先讲为什么还没有。C++ 没有反射的原因,是因为还没有人提出一个反射的提案,能够在标准委员会里得到充分的认可,达成“共识”,从而进入 C++ 标准。
一个特性要进入 C++ 标准是很难的。C++ 已经有了很多的特性,被认为是一种非常复杂的语言。这种情况,加特性需要非常慎重,需要总体上有足够的提升,同时不会太多加重学习者的负担,还要满足 C++ 的零开销抽象之类的理念,门槛是相当高的。加上这两年由于疫情影响,C++ 标准委员会开会也大多通过远程,影响了沟通效率,进展速度上总体偏低。
但没有反射只是现状,不是未来。C++ 里反射,更精确地说是“静态反射”,一直是一个热烈讨论中的话题。有很多的标准提案和讨论。Bjarne 老爷子在 HOPL4 论文里也讨论了 2013 年以来的进展。中文版参见:
《在拥挤和变化的世界中茁壮成长:C++ 2006–2020》§9.6.2我强烈推荐 Andrew Sutton 在这方面的工作。他的关于静态反射的演讲也都非常棒,比如:
Reflection: Compile-Time Introspection of C++ - Andrew Sutton [ ACCU 2021 ]但可惜的是,在 C++23 的时间窗里还是没有静态反射,我们至少需要等到 C++26 了……
<hr/>那我们现在怎么办呢?——可以利用模板和宏来自己实现。
我在项目中已经自己实现和使用静态反射相当一段时间了。最典型的应用,正如别人提到的,是序列化和反序列化。其他我用到的用法还有:

  • 用通用的函数模板来打印支持反射的结构体
  • 用通用的函数模板来对结构体进行逐成员的比较
  • 用通用的函数模板来复制异质同构的结构体(成员之间有一一对应关系,但类型可以不同)
  • 在复制中逐成员进行字节序转换
  • 复制两个结构体中的同名字段
  • ……
项目代码不是开源的,不能直接分享。目前我知道的关于自己实现静态反射的中文资料是:

  • @netcan 的《如何优雅的实现 C++ 编译期静态反射》
  • 我的极客时间专栏的第 40 讲(预计 2022/06/27 下周一上线)
罗能的文章中讲述了静态反射的基本原理,而我的工作则基于他的思想进行了进一步的拓展。(如果我没记错的话,虽然极客时间是需要付费的,但任何专栏都可以免费读四讲,所以你完全可以在本周之后过去只读那一讲。)
我最后实现的效果是,对于下面的代码:
DEFINE_STRUCT(
  S1,
  (int)v1,
  (bool)v2,
  (string)msg
);

DEFINE_STRUCT(
  S2,
  (long)v1,
  (bool)v2
);

S1 s1{1, false, "test"};
S2 s2;
copy_same_name_fields(s1, s2);
编译器可以产生下面这样的高效汇编代码:
movsx   rax, DWORD PTR s1[rip]
mov     QWORD PTR s2[rip], rax
movzx   eax, BYTE PTR s1[rip+4]
mov     BYTE PTR s2[rip+8], al这显然是其他支持反射的语言所无法做到的!
发表于 2023-8-22 17:03 | 显示全部楼层
有template还要反射干什么
高级语言中的模板,反射,元类,动态修改字节码等技术统统都是元编程范畴的,所谓元编程,一句话就能讲明白,就是program as data,把程序本身当作数据,对程序进行操作。这么一说聪明的你是不是若有所思,没错,C语言中的macro也是元编程范畴的
https://en.wikipedia.org/wiki/Metaprogramming回到主题,C++有没有什么“反射”用在项目里的例子?有的,比如浏览器内要实现各种各样的样式,每个样式在浏览器引擎内都有对应的C++类,类似的样式可能有好几百种,比如BackgroundColor这个样式,这些类的代码没有必要一笔一笔的手写,有构建工具在编译期自动生成代码
https://chromium.googlesource.com/chromium/src/third_party/+/master/blink/renderer/build/scripts/core/css/properties
发表于 2023-8-22 17:03 | 显示全部楼层
编译结果决定了他们不能简便进行运行时反射。但是在link或者编译期间的反射还是可以做的。
发表于 2023-8-22 17:04 | 显示全部楼层
反射的实现并不难,很多C++库都实现了反射,如Qt、UE4、protobuf里面都有反射。UE4不仅有反射,还有垃圾回收。
但是标准C++追求的是零开销,像Qt/UE4/protobuf/java/golang那种反射入不了标准委员会的法眼。标准C++的思路是提供编译期反射(相关提案名为Reflection TS),目前进度喜人,距离可用大概需要3~6年。
想进一步了解Reflection TS的用法及目前进度可以看这个文档:
https://github.com/boostcon/cppnow_presentations_2019/blob/master/05-08-2019_wednesday/The_Cpp_Reflection_TS__David_Sankel__cppnow_05082019.pdf2022-1-7更新:clang reflection分支已经实现了reflection ts,可以在这里试用:
Compiler Explorer - C++ (x86-64 clang (reflection))2022-10-22更新:反射已经被列为C++26的三大主要目标之一,文档:
To boldly suggest an overall plan for C++26
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-3 05:20 , Processed in 0.105635 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表