c ++发出内联函数

时间:2016-02-14 21:09:00

标签: c++

让我们说我有一个包含函数void foo();的公共定义的库。库在内部调用此函数。为了获得最佳性能,我希望内联调用内联。我还想防止外部代码看到定义,以便以后我可以在不破坏ABI的情况下更改实现。这是一段代码:

MyLib.h:

void foo();

MyLibInlined.h:

inline void foo() { code here }

MyLib.cpp

#define inline
#include "MyLibInlined.h"

问题是它是否打破了ODR还是被视为不良做法?

修改 如果foo是成员函数怎么办?

4 个答案:

答案 0 :(得分:4)

  

问题是它是否打破了ODR还是被视为不良做法?

它不会破坏ODR,但会破坏[dcl.fct.spec]中的规则:

  

如果是具有外部链接的功能   在一个翻译单元中内联声明,应在其出现的所有翻译单元中内联声明;   无需诊断。

相反,您应该拥有该函数的公共版本,该函数未声明为内联版本,并且具有您在库中使用的内部版本:

// MyLibInlined.h
inline void foo_impl() { }

然后在库内定义foo作为内部调用:

// MyLib.cpp
#include "MyLibInlined.h"
void foo() { foo_impl(); }

或者,如果对foo()的所有调用都在一个文件中,您根本不需要担心,只需将其定义为非内联函数,并让编译器将其内联在文件中定义是可见的:

// MyLib.h
void foo();

// MyLib.cpp
void foo() { code here }
// use foo ...

inline关键字并不意味着函数将被内联,这意味着定义是在标题中内联提供的。编译器不需要该关键字能够在定义它的文件中内联它,因为它可以看到定义。您只需inline关键字即可让定义出现在多个翻译单元中,而不会导致多重定义错误。

答案 1 :(得分:0)

AFAIK确实打破了ODR,因为内联并不是一个规则,因为它是一个指导原则。尽管声明了这些函数,但允许编译器不内联函数。

另一方面,编译器也允许内联未声明的内联函数,并且可能在内部调用中对小函数执行此操作(在某些情况下,它可以在链接时执行),所以只需要&# 39;不用担心。

或者在单独的命名空间中声明内联版本,并使用内联命名空间在编译时解析它(或使用或其他)(http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces

答案 2 :(得分:0)

基于此(C ++ 14 3.2 / 6)

似乎是非法的
  

内联函数可以有多个定义   程序中的外部联系[...]提供了每个定义   出现在不同的翻译单元中,并且定义满足以下要求。特定   这样一个名为D的实体在多个翻译单元中定义,然后

     

[...]

     

- D的每个定义应由相同的令牌序列组成

第3.2节是关于一个定义规则的部分。

答案 3 :(得分:0)

这可能是你正在做的更清晰的变化:

// foo_pub.h -- public interface
#define foo()   foo_pub()
void foo_pub();

// foo_private.h -- internal used by library
#define foo()   foo_inline()
inline foo_inline() { ... }

// foo_pub.c -- definition for public function
void
foo_pub()
{
    foo_inline()
}