为何C++20模块导出的函数名字修饰会包含模块名?
为何C++20模块导出的函数名字修饰会包含模块名?
咱们先从实际例子说起:
export module A; export void a(int);
int main() { a(42); }
在Linux环境下,这个a函数会被名字修饰为_ZW1A1ai,还原后是a@A(int)——确实把模块名A嵌进去了。
你可能会好奇:非导出函数加模块名很好理解,毕竟模块内部的函数要在多个编译单元里复用,又不能和外部模块的符号冲突;但为什么导出的函数也要带模块名修饰呢?
这其实是C++20模块设计里「强模块所有权(strong module ownership)」的策略——不管函数是否导出,都把模块名加入名字修饰中。对应的还有另一种「弱模块所有权(weak module ownership)」:只给非导出函数的名字加模块名,导出函数不加。
那强所有权的优势在哪?核心就是彻底避免不同模块间导出符号的命名冲突。比如如果有模块A和模块B都导出了一个void a(int),要是导出函数不带模块名修饰,链接时就会因为符号重复直接报错,你没法在同一个程序里同时使用这两个模块的同名函数。但用了强所有权后,两个函数的修饰名会带上各自的模块名,被视为完全不同的符号,你就可以通过导入不同模块的方式分别调用它们,这大大提升了模块的独立性和可复用性。
至于你提到的用extern "C++" {...}可以禁用这个行为,这确实是一个可选方案,但这么做就等于主动放弃了强模块所有权的符号隔离保护,需要你自己去确保整个程序里没有同名的导出符号冲突,风险得自己把控。
备注:内容来源于stack exchange,提问作者HolyBlackCat




