命名空间中的内联函数在 gcc 上的链接期间生成重复的符号

Posted

技术标签:

【中文标题】命名空间中的内联函数在 gcc 上的链接期间生成重复的符号【英文标题】:inline function in namespace generate duplicate symbols during link on gcc 【发布时间】:2011-04-15 09:25:12 【问题描述】:

我有一个带有内联函数的命名空间,如果有多个源文件将使用它。 尝试链接我的应用程序时,内联函数报告为重复符号。 似乎我的代码根本不会内联函数,我想知道这是否是预期的行为以及如何最好地处理它。

我使用以下 gcc 选项: -g -Wextra -pedantic -Wmissing-field-initializers -Wredundant-decls -Wfloat-equal -Wno-reorder -Wno-long-long 在 VC7 环境中构建时,相同的代码样式似乎可以正确编译和链接。

以下代码示例显示了代码的结构:

/* header.h */
namespace myNamespace 
inline bool myFunction() return true;


/* use_1.cpp */
#include "header.h"
...
bool OK = myNamespace::myFunction();
...

/* use_2.cpp */
#include "header.h"
...
bool OK = myNamespace::myFunction();
...

【问题讨论】:

每个cpp文件中的全局变量可以吗?这将导致重复符号错误。假设它不是全局的,那么您的示例是合法的 C++。尝试使用 -Winline 进行编译。你用的是什么版本的 gcc? 请发布实际的编译器消息。最小的源文件是否会发生错误(只是提到的行没有...所暗示的东西)? 一旦我将OK 的名称之一更改为OK1,添加了一个空的main 函数并删除了...;使用您提供的选项编译这两个文件对我来说是正确的。您需要发布更多详细信息,因为您的错误原因不在这里。 【参考方案1】:

删除 dll/exe 的构建目录并重新编译。

构建可能存在一些问题。它可以是 OP 在上面的评论中提到的预编译头文件。我遇到了完全相同的问题,删除构建目录并重新编译解决了它。

【讨论】:

【参考方案2】:

inline 关键字仅被编译器用作提示。如果编译器决定该函数在没有内联的情况下会更好地执行,它将不会内联它。有一些特定于供应商的关键字可以使编译器内联一个函数 - 对于 GCC,它是 __attribute__((always_inline)),对于 Visual C++,它是 __forceinline。 如果您真的想确保您的函数不会在所有标准编译器的所有情况下导致链接器错误,您可能希望将其模板化,因为即使在标头中定义模板化函数也保证不会导致链接器错误。但是,对于非常简单的函数来说,这是完全没有必要的。

【讨论】:

如果您编写得当,您的代码不会导致链接器错误。在不需要的地方编写模板是无稽之谈。 C++ 编译器是否内联函数在这里并不重要。编译器在 as-if 规则下透明地处理这个问题。然而inline 会影响程序的语义。不管编译器是否真的内联函数,这里都是合适的。请研究“一个定义规则”。 已解决:我终于有时间追查问题的根源,而且(通常)这是一个使用预编译头文件的简单一致性问题。我了解到,内联的使用实际上是透明的,并且不需要注意编译器是否真的内联函数。最重要的是:在使用预编译头文件时始终使用 -Winvalid-pch 标志。

以上是关于命名空间中的内联函数在 gcc 上的链接期间生成重复的符号的主要内容,如果未能解决你的问题,请参考以下文章

命名空间内的局部函数声明

非内联命名空间不能作为内联重新打开

为啥 range-v3 将其函数对象放入内联命名空间?

C++入门语法第一篇:(命名空间缺省参数函数重载引用内联函数)

C++初阶:入门总结命名空间 | 缺省参数 | 函数重载 | 引用 | 内联函数

C++入门(命名空间缺省参数函数重载引用内联函数)