C ++:正确的内联语法

时间:2010-06-24 07:59:53

标签: c++

是否首选定义内联方法,如:

// math.h
class Math
{
public:
    inline static int sum(int a, int b)
    {
        return a + b;
    }
};

// math.h
class Math
{
public:
    static int sum(int a, int b);
};

// math.cpp
inline int Math::sum(int a, int b);
{
    return a + b;
}

为什么?有什么区别吗?你应该完全放弃内联编译器吗? (我知道这是非常主观的,但我想听听一些意见和理由)

此外,我相信大多数编译器都会内联或不自行内联,无论是否存在内联关键字?

8 个答案:

答案 0 :(得分:4)

无论如何,你都要完全放弃内联编译器。这些只是提示您认为代码应该内联(或不是)。默认情况下,类定义中定义的所有方法都是内联的(inline的实际含义不是必须内联此方法)。

class Math {
public:
   static int sum( int a, int b )  // inlined even without 'inline'
      { return a+b; }
};

您是否使用了类内或类外的内联版本(两者都在标题中)取决于您,我将基于可读性。对于小型单行和访问器,我倾向于在课堂上编写它们,因为这是该方法最强大的文档,代码仍然可以让您轻松地看到类接口。

答案 1 :(得分:2)

内联 完全取决于编译器。与旧的C inline关键字一样,register关键字是建议编译器进行一些优化。

但是,编译器编写者比他们对目标体系结构的了解要多得多,这确实是不必要的。

因此,我不会使用inline所以这个问题没有实际意义(对我而言)但是我宁愿保留所有代码,因为这总是导致C编译器中出现双重定义的符号

将代码放入头文件中也会不必要地泄漏信息。使用标题的人不应该看到实现细节。

答案 2 :(得分:2)

如果您使用第二种方法会遇到麻烦,那就是在编译包含math.h的其他源文件时,他们不会知道您的Math::sum函数的定义。因此,他们无法内联它。

这就是为什么你应该把函数的定义放在头文件中。但请注意,您可以在定义类之后编写它。写入它不是强制性的。

答案 3 :(得分:1)

我们在公司中使用的是帮助在调试版和发布版中进行更好权衡的常用技巧。您并不真正关心调试版本中的内联,但是您更希望将内联代码分离,以避免在触摸内联代码时长时间重新编译。所以我们这样做:

// math.h
class Math
{
public:
    static int sum(int a, int b);
};

// At the very end of math.h
#ifndef _DEBUG
#include "math.inline.h"
#endif

// math.inline.h
#ifdef _DEBUG
#define INLINE
#else
#define INLINE inline
#endif

INLINE int Math::sum(int a, int b);
{
    return a + b;
}

// math.cpp
#include "math.h"
#ifdef _DEBUG
#include "math.inline.h"
#endif

这样,math.inline.h的全部内容在两个版本中都完全相同(就在math.h的末尾),但它们仅包含在发行版本中的头文件中。调试版本将它们与实现文件一起包含在内,并且永远不会尝试内联函数。

答案 4 :(得分:1)

您的第二种方式是,math.cpp以外的其他任何翻译单元都不允许拨打Math::sum ,因为标准说明内联函数应在每个翻译单元中定义使用它们。完全可能这会给你一个链接时错误(我之前遇到过这个问题)。

始终在标题中定义内联函数以避免此问题。

答案 5 :(得分:0)

与编译器使用这两种方法中的任何一种方法没什么区别

但一般来说,它首选的头文件只包含声明,只是规范类接口,这样任何人都可以查看头文件,无需进入如何实现功能。因此,最好在头文件中使用接口规范并在.cpp文件中实现

答案 6 :(得分:0)

编译器通常可以跨翻译单元移动代码,因此两者应该没有区别。我个人更喜欢这个(全部在标题中):

// math.h
class Math
{
public:
    static int sum(int a, int b);
};

inline int Math::sum(int a, int b)
{
    return a + b;
}

我更喜欢这个的原因是,有些时候即使是最好的优化编译器也不能内联代码,如果你把它放在cpp文件中,就像数学类被导出一样(没有跨越DLL边界的内联,例如)。我不喜欢对我的编码风格进行例外处理,因此只需将它放在标题中就可以允许编译器内联它(如果它选择的话)。

我更喜欢这种显式样式而不是直接在类定义中内联的第二个原因是因为我与许多懒惰的编码人员合作,他们经常内联事物只是因为它节省了编写时间而不是在分析会话后实际内联(这是通常你唯一应该考虑内联,除非你是一个优秀的编译器/汇编天才)。

作为一个重要的侧面说明,很常见的是内联在性能方面没有明显改善,并且在许多情况下,内联代码不比内联更好。我发现这甚至适用于简单的一行访问器函数:只是因为代码在内联时需要的指令少于调用函数所需的指令,并不总是意味着编译器会用它做得更好。过度内联实际上可能会混淆编译器(例如:由于过多的内联,异常情况代码访问内存而不能非常有效地使用寄存器)。内联真的应该小心谨慎并借助分析器。

答案 7 :(得分:0)

有时,当方法是单行时,第一个版本可以作为一种文档形式。