【问题标题】:Is "inline" implicit in C++ member functions defined in class definition在类定义中定义的 C++ 成员函数中是否隐含“内联”
【发布时间】:2012-02-08 11:04:34
【问题描述】:

根据C++规范,下面两个类是等价定义的吗?

class A
{
   void f()
   {
   }
};

class B
{
   inline void f()
   {
   }
};

即,将“内联”限定符放在类定义中定义的此类成员函数上是否完全多余?

后续问题:假设它是多余的,对于代码风格,保留“内联”标签是否明智,因此未来的开发人员意识到应该内联函数,并且不会在其他地方删除定义并删除内联?

谢谢:)

【问题讨论】:

  • 请注意——我知道“内联”只是对编译器的提示。这个问题与此无关。
  • 只是一个提示。它有一个重要的意义。这意味着与内联无关,它与 ODR 有关。这也是关于内联的提示。
  • 不确定这在 9 年前是否属实,但现在 inline 与实际内联的函数没有任何关系。这取决于编译器。

标签: c++ class inline


【解决方案1】:

C++ ISO 标准说:

在类定义中定义的函数是内联函数。

但是,这并不意味着函数必须被内联:通常现在,编译器似乎会决定内联函数是否会带来任何好处。

【讨论】:

  • 我同意 Cort 的观点。这应该是公认的答案。为了验证,ISO C++11 标准的第 7.1.2 节(标题为“函数说明符”)第 3 项逐字说明他所说的:“在类定义中定义的函数是内联函数。”
  • 许多人不知道在类定义中声明的函数的这种底层内联。这很有帮助。
【解决方案2】:

除了单一定义规则的目的之外,它们是等效的类定义。所以标准不保证你可以用一个类定义编译一个 TU(翻译单元),用另一个类定义编译一个不同的 TU,然后将它们链接在一起。我怀疑这在真正的实现中是否真的会失败,但这就是标准所说的。

inline 关键字与内联几乎无关。这是关于在不同的TU中是否允许函数的多个相同定义。如果有人将函数定义移到别处,那么他们应该根据以下基础决定是否将其标记为inline

  • 如果它位于该类的 .cpp 文件中,则如果仅从该 TU 调用它,则将其标记为 inline 是有效的。那么它是否标记为inline 可能没有区别,但是如果你认为编译器会注意你想要的东西,你可以将它标记为inline 作为编译器提示。

  • 如果还在头文件中,则必须标记为inline,否则在链接使用头文件的不同TU时会出现多个定义错误。

假设移动函数的人知道这些事情,我认为他们不需要在类定义中进行提醒。如果他们不知道这些事情,那么他们可能没有必要移动该函数,但对他们来说,使用 inline 关键字来移动它会更安全。

【讨论】:

  • 我猜TU应该是“翻译单位”。刚刚想通了,为方便其他人在这里评论。
  • 对于 clang,关键字 inline 实际上会影响函数内联以及 ODR 规则。 stackoverflow.com/questions/27042935/…
  • This answer 引用 C++98 标准的话说,可以在其类定义中定义(8.4)成员函数,在这种情况下,它是内联成员函数(7.1. 2) 这似乎与答案的第一句话相矛盾;根据标准的引用,两个类定义都定义了内联成员函数f,这是 ODR 明确允许的。
  • @user4815162342:class A {void f() {}};class A {inline void f() {}}; 都是允许的,但 ODR 禁止您在不同的 TU 中使用它们中的每一个,然后将这两个 TU 链接在一起。 ODR 允许链接内联函数的两个定义(以及一个类的两个定义),前提是它们相同,这意味着它们必须由相同的标记序列组成。由于一个定义包含令牌inline 而另一个不包含,因此不允许它们在同一程序中同时定义相同的类A
  • 感谢您的澄清,我忘记了“相同的令牌序列”要求。在“出于 ODR 的目的”旁边的答案中提及该要求可能是一个好主意,因为如果将两个类命名相同,那将是唯一使这两个类“不同”的原因。
【解决方案3】:

将“内联”限定符放在类定义中定义的此类成员函数上是完全多余的吗?

是的

对于代码风格,保留“内联”标签是否明智,以便未来的开发人员意识到函数应该内联,而不是在其他地方删除定义并删除内联?

没有。
内联用于“一个定义规则”(因此通过扩展链接)。如果在需要inline 的位置定义了函数并且未提供该函数,则为编译时错误。如果不需要,那只是多余的无用的绒毛。

因此,如果您不需要它,请将其删除。如果你需要它把它放在那里(如果你忘记了编译器会让你知道的)。

【讨论】:

    【解决方案4】:

    在这种情况下,内联是可选的,是的。只要包含头文件,编译器就会知道它是内联的,并且不会生成函数的多个实例。

    至于把它留在那里是否是个好主意 - 我真的不这么认为。最好给出一个详细的评论来解释为什么必须内联函数(其中我只能排除两个原因:“它是一个模板”在这种情况下是不可能的,或者是“性能”在这种情况下我希望看到一些支持证据,而不是我在某些地方看到的“它必须表现更好,因为它是内联的”。

    【讨论】:

      猜你喜欢
      • 2013-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-16
      • 2015-10-27
      • 2018-12-15
      相关资源
      最近更新 更多