为什么类成员函数内联?

vid*_*dit 28 c++ compiler-construction inline class function

我想我之前已经问过我的问题了,我确实读了它们但仍然很少混淆,因此要求说清楚.

The C++ standard says all member functions defined inside class definition are inline

我也听说编译器可以忽略函数的内联.在上述情况下是否会成立,或者如果在类定义中定义,它将始终内联?

此外,这个设计背后的原因是什么,使所有函数在类定义中内联定义?内联与源文件和头文件有什么关系?

更新:所以如果不进行内联,应该总是在课外定义它们的功能,对吧?

JohnB的更新2: 在类定义中声明的两个函数永远不能互相调用,因为它们必须包含另一个函数的整个主体.在这种情况下会发生什么?(已由Emilio Garavaglia回答)

Emi*_*lia 41

出现混乱是因为内联有两个影响:

  1. 它告诉编译器可以在调用函数的地方扩展函数代码,而不是有效地调用它.
  2. 它告诉编译器可以重复函数定义.

第1点是"过时的",因为编译器实际上可以按照自己喜欢的方式来优化代码.它总是"内联"机器代码,如果它可以找到方便的话,如果它不能,它将永远不会这样做.

第2点是该术语的实际含义:如果您define(在主体中)指定一个函数,由于标题可以包含在更多的源中,您必须告诉编译器通知链接器有关重复的定义,以便他们可以合并.

现在,根据语言规范,自由函数(未在类体中定义)默认情况下未定义为内联,因此在头文件中定义类似于

void myfunc()
{}
Run Code Online (Sandbox Code Playgroud)

如果标头包含在更多源中,然后在同一输出中链接,则链接器将报告多重定义错误,因此需要将其定义为

inline void fn()
{}
Run Code Online (Sandbox Code Playgroud)

对于类成员,默认情况相反:如果您只声明它们,则不会内联它们.如果您定义它们,它们将是内联的.

所以标题应该是这样的

//header file

class myclass
{
public:
    void fn1()
    {} //defined into the class, so inlined by default

    void fn2();
};

inline void myclass::fn2()
{} //defined outside the class, so explicit inline is needed
Run Code Online (Sandbox Code Playgroud)

如果myclass::fn2()定义进入适当的来源,则必须丢失inline关键字.

  • 可以认为语法中的_inline_字表示"此函数的定义将内联到多个转换单元而不会破坏ODR".即内联源代码级别,而不是机器代码. (2认同)

iam*_*ind 11

inline关键字具有函数2的含义:

  1. 代码替换:无论在何处inline调用函数,都不要为它生成函数调用,只需将函数的内容放在其调用的位置(这类似于宏替换,但类型安全)
  2. 一个定义规则:不要为inline函数生成多个定义,只生成所有共同的单个定义(例外:static函数)

第1个术语("代码替换")只是对编译器的请求.这可以忽略,因为编译器最好判断是放文本还是函数调用.(例如,virtual函数或递归函数不能内联).

第二个术语("一个定义规则")保证由任何符合标准的编译器发生.这将为所有翻译单元仅生成1个定义.这个工具有时可以简化编码器的工作,因为对于较小的功能,人们可能不希望将其定义放在.cpp文件中(例如,getter,setter).
而且,对于template仅作为标题构造的函数,这种效果是强制性的.因此默认情况下template是函数inline.

例子:

class A {
public:
  void setMember (int i) { m_i = i; }
};
Run Code Online (Sandbox Code Playgroud)

在这个例子中,大多数编译器都足以满足这两个术语

class A {
  inline virtual ~A () = 0;
};
A::~A() {}
Run Code Online (Sandbox Code Playgroud)

这里编译器只能满足第二个要求.


BЈо*_*вић 8

使方法函数内联的唯一原因是如果在头文件中定义它.

如果在标头中定义方法函数,并且未放入内联关键字,并且在多个标头或源文件中包含标头,则可以获得该方法的多个定义.

9.3/2成员函数中的c ++ 11标准[class.mfct]告诉:

成员函数可以在其类定义中定义(8.4),在这种情况下,它是内联成员函数(7.1.2)......