如何__forceinline VS2008的功能?

时间:2016-05-28 04:31:49

标签: c++ windows visual-studio visual-studio-2008 mfc

我需要在Visual Studio 2008(MFC项目)中编译的C ++项目中“强制内联”以下方法:

//.h file
__forceinline static BOOL IsLicenseGood(LIC_NAME_NUMBER& lnn);

//.cpp file
__forceinline BOOL CMyClass::IsLicenseGood(LIC_NAME_NUMBER& lnn)
{
    //Do checks
    ...
    return result;
}

但是当我为release版本编译它时,它会给我以下重复警告:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xmemory(154) : warning C4506: no definition for inline function 'BOOL CMyClass::IsLicenseGood(LIC_NAME_NUMBER &)'
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\vector(46) : warning C4506: no definition for inline function 'BOOL CMyClass::IsLicenseGood(LIC_NAME_NUMBER &)'

知道那里有什么问题吗?

2 个答案:

答案 0 :(得分:1)

内联工作有两种方法。

“经典”方式是编译器在从源代码到机器代码的转换过程中(确切地说,这里没有很好地定义,而且不同的编译器供应商可能会稍微不同地这样做)。这个方法要求源代码对于内联函数是可用的 - 否则,编译器如何内联呢?因此,为了使其一般工作,该函数必须仅在一个源文件中使用(并且不需要在任何头文件中声明),或者该函数可以在几个地方使用,只要它被定义在调用代码包含的头文件中。

在你的情况下,编译器抱怨它不能这样做,因为只有声明在头文件中可用,而不是定义 - 所以编译器说“但你怎么指望我做你做的“我问道,没有告诉我要内联的内容”。

“新”方式称为“链接时间优化”或“整个程序优化”(取决于您所讨论的编译器)。这只是将源文件部分编译成源的一些中间表示 - 不是源代码,而不是实际的机器代码,它们之间的某种程度,它有关于“代码是什么”的更多信息。当最终的可执行文件然后链接在一起时,生成机器代码。在此阶段,还执行内联过程,这意味着即使编译器在编译期间无法看到该函数,也可以内联合适的函数。

这允许从“任何地方”内联,但需要为链接器选项设置不同的设置。我希望forceinline仍然会被警告,因为那时的编译器不知道你是早进还是晚进行内联 - 虽然我不是百分之百确定。

SIMPLE问题的答案是将定义(函数体)移动到头文件,并完成它。或者删除forceinline关键字。

答案 1 :(得分:0)

我做了一些研究,我能够尽可能少地完成我想要的改变。我需要注意的是,我使用Visual Studio 2008 C ++编译器测试它 ,因此我不确定它是否可以与其他编译器一起使用。以下是内联函数的步骤:

  1. 将整个函数移动到声明.h文件中。它完全打破了.h文件中我的函数声明的一个很好的布局,但是......很好。

  2. 仍然使用__forceinline指令。我的测试表明,对于放入.h文件的小函数,它会自动内联。更复杂的功能,不是。幸运的是,微软的编译器似乎是"荣誉" __forceinline指令并内联更大的函数。

  3. 所以函数看起来像这样:

    //.h file
    static __forceinline BOOL IsLicenseNumberGood(LIC_NAME_NUMBER& lnn)
    {
        //Place the entire function code into .h file here
        ...
        return result;
    }
    

    现在我在处理这个问题时出现的第二个问题是如何知道你的函数实际上是内联的?显然没有内置的方法来检查它。所以我提出了以下步骤。如果你知道更好的方法,请随时纠正我?

    • 显然要构建一个Release项目(因为Debug配置不会内联。)

    • 添加一些测试标记,以区分所涉及功能的结果机器代码。我正在构建一个32位模块,所以我仍然可以使用asm指令添加一些内联汇编。我选择了这个,因为很容易添加一些无害的机器代码,否则编译器不会添加它们。 (如果您使用64位代码,那么您将不得不做其他事情。也许使用一些独特的API调用,例如GdiFlush,它不会改变任何内容。)

      < / LI>
    • 最后,在完成测试后,删除装配标记。

    所以这里是C ++视图中方法的快照:

    enter image description here

    Release配置构建它之后,在需要检查内联并开始调试(或点击F5)的方法上设置一个断点。

    当断点触发时,切换到反汇编视图(或按Alt + 8)。你应该看到开放的三元组asm命令:

    enter image description here

    然后,如果函数成功内联,则会看到大量的汇编程序代码而不包含C ++代码。这将是您内联函数的机器代码。你可以进入它并按照asm逻辑,如果你知道要仔细检查。

    在我的例子中,内联方法稍后结束了大约1K字节,并在最后添加了关闭三元组asm命令:

    enter image description here

    所以这似乎对我有用。它是一种完全手动的方法,但它有效。

    感谢所有贡献的人!

相关问题