0

我一直想知道,两次定义琐碎的方法是好还是坏的做法,这取决于
项目是否处于调试/发布状态。这是为了内联它们。例如,Foo.h:


class Foo
{
        public:
                ...

                const bool& IsBoolean() const;

        private:
                bool _boolean;
};

#ifndef _DEBUG

/** We're in release, so let's advice compiler to inline this...
  *
  *
  */

inline const bool& Foo::IsBoolean() const
{
        return _boolean;
}

#endif

现在,在 Foo.cpp 中:


#include "Foo.h"

...

#ifdef _DEBUG

/** We're debugging this, no need for inlining...
  *
  *
  */

const bool& Foo::IsBoolean() const
{
        return _boolean;
}

#endif

这完全没用吗?例如,由于编译器(MSVC)本身内联/优化方法的能力?

尽管如此,这是我多年来一直在使用的东西。请纠正我,如果我在这里完全错了......

4

4 回答 4

9

这是浪费时间,有几个原因。

inline 关键字是编译器可以随意忽略的提示。就像即使没有指定关键字也可以自由内联。因此,无论您是否添加它都可能不会改变编译器的任何内容

此外,在类定义中定义的任何函数都是隐式内联的。这就是为什么像 getter 和 setter 这样的短函数几乎总是在类定义中定义。

接下来,如果您想将函数标记为内联,也没有理由不在调试版本中执行此操作。

inline关键字几乎与编译器实际上内联函数无关。它们是不同的概念。程序员标记inline的函数意味着链接器在看到多个相同的定义时不必担心。如果函数在标头中定义,通常会发生这种情况,该标头包含在多个编译单元中。如果函数被标记为内联,链接器会将定义合并在一起。如果不是,则会出现错误。换句话说,添加和删除此关键字将导致编译器错误。这可能不是你想要的。

C++ 关键字和编译器优化之间有一点重叠的唯一原因inline是,如果一个函数被标记inline,那么在每个编译单元中 #include 它是安全的,这意味着当函数被调用时定义总是可见的. 这使得编译器更容易内联对函数的调用。

最后,内联并不总是一种性能改进。很容易造成这样的情况:内联只会使代码大小爆炸,导致更多的缓存未命中,并且总体上会减慢代码的速度。inline这就是优化器(充其量)将其视为提示的原因之一。在最坏的情况下,它会被完全忽略。

因此,您所做的将 1)在调试模式下导致发布版本中不存在的编译器错误,以及 2)对性能没有影响。

于 2009-05-26T20:57:37.423 回答
2

看起来像浪费空间和不必要的代码重复。通常,编译器非常有能力自行确定哪些函数需要内联,哪些不能。如果您使用的是具有/LTCG(链接时间代码生成)开关的 MSVC,则更是如此,这意味着您的琐碎方法即使在 cpp 中也会被内联。

于 2009-05-26T20:48:03.463 回答
1

重复是不好的。即使你正在处理一个脑残的编译器,你也可以很容易地避免这种重复,最坏的情况是,通过使用在一个地方INLINE定义的宏来要么要么不做,要么什么都不做。inline

于 2009-05-26T20:47:53.573 回答
1

做你想做的最简单的事情是将代码放入它自己的文件filename.inl中,然后有条件地将文件包含到头文件或源文件中。您还应该为.inl文件中的函数添加一个条件宏前缀,如果文件包含在标题中,则该条件宏扩展为内联,否则为空宏。

于 2009-05-26T20:53:02.020 回答