类中的内联函数成员

69

我知道在函数定义很小且需要性能优化时,将函数声明为inline是一种好的做法,并且它会节省编译时间。但是如何处理类内的inline方法呢? 我不太理解类内的inline方法概念,如何定义它们以及它们是如何工作的。


11
"当函数定义较小且需要考虑性能以及编译时间时,这是一种良好的实践方法。" - 你在哪里读到的? - Oliver Charlesworth
@OliCharlesworth : 我的意思是,如果函数只包含一两条语句,将该函数声明为内联函数可以节省编译器执行跳转到定义处的时间,尤其是当该函数被大量调用时。 - AlexDan
6
请注意,由于编译器会在每个调用点生成内联函数的代码,因此您可能并没有帮助缩短编译时间。过度的内联将降低编译时间并增加可执行文件的大小。 - brendanw
5
仅作澄清,内联声明并不会在编译时节省时间,而是通过增加代码大小来节省代码执行时间。 假设您将代码放入函数中需要500字节。如果不使用内联,则函数将使用500字节,但CPU需要“跳转”到该函数,浪费时间。使用内联后,每次调用代码将使用500字节,但速度更快。 基本上,内联建议编译器优先考虑速度而非大小,在执行时间至关重要的嵌入式环境中(例如中断)非常有用。 - Ramon La Pietra
以下链接是IBM提供的一个简短但非常好的解释。https://www.ibm.com/support/knowledgecenter/zh/SSLTBW_2.3.0/com.ibm.zos.v2r3.cbclx01/inline_member.htm - TheArchitect
3个回答

69

但是在类内部定义的内联方法呢?

使用显式的inline和在类定义内部定义成员函数的两种语法都只提供编译器有关内联的提示。从性能角度来看,它们是相等的。

对于在类声明中定义成员函数的情况,可读性应该是您最关心的问题:用多行实现细节污染类接口会让人很不舒服。因此,如果成员函数超过一个语句,请避免这样做:return stuff或简单转发应该可以,但通常不要超过这个范围。

class MyClass
{
public:
    int f() const { return m_i; }
    int g() const;

private:
    int m_i;
};

inline int MyClass::g() const
{
    return m_i;
}

// both member-functions behave equally (except for naming)

函数 g() 的声明和定义必须与 main() 函数在同一文件中,或者可以只在一个文件中编写函数 g() 的声明,而在另一个文件中编写其定义。 - AlexDan
7
定义可以放在单独的“文件”中,但它需要在调用 g() 的代码所在的同一个“翻译单元”中。这有效地意味着定义应该包含在包含调用的源文件中。 - Alexander Poluektov
这是否意味着类定义内部的函数定义会自动被视为内联?如果不是这种情况,为什么可以在不同文件中定义相同的类(具有相同函数),而不会违反函数的一次定义规则? - Albert
@Hal 是的,它确实如此。 - Alexander Poluektov
“(除了命名)”这是指编译后的函数命名吗? - kyb

28

在类内将函数/过程指定为 inline,是向编译器暗示,代替创建调用函数并传递参数的代码,应该将函数内容放置在调用点。

这可以提高编译生成二进制代码的性能,因为执行函数而无需传递参数更加有效率。但也可能降低性能,因为在每个调用位置重复函数中的代码会导致臃肿,减少代码在更快缓存内存中的发现概率。


27

为了使一个类的函数成为内联函数,编译器提供了两个选项:

(1) 在类的声明中定义该函数(在头文件中)

class Human {

public:

    Human(const char* name);
    Human();

    // is implicit inline
    void lookAt(const char* name) const {
        std::cout << "I'm looking at " << name << std::endl;

    }

private:
    char _name[30]; 

}; 

(2) 在函数定义中(在头文件中),显式使用inline关键字

    // is explicit inline 
    inline void lookAt(const char* name) const {
        std::cout << "I'm looking at " << name << std::endl;

    }

14
你不能将inline方法放在.cpp文件中,它仍然必须放在头文件中。 - KayEss
9
是的,你说得对。如果我将内联函数定义放在.cpp文件中,链接器将会报告“未解析的外部”错误。因此无论是显式还是隐式,内联函数都必须放在头文件中。 - Jan Koester
2
有一个例外:只在cpp文件中使用的私有内联函数可以在那里定义... - Aconcagua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接