内联此功能,有意义吗?

时间:2019-07-26 19:03:59

标签: c++ templates winapi inline

我有下一个成员函数:

template <typename T>
inline T Foo::Read(const DWORD addr) const                          // Passing by value.
{
    T buffer;
    ReadProcessMemory(m_processHandle, (LPVOID)addr, &buffer, sizeof(T), NULL);
    return buffer;
}

如果我没记错的话,当编译器内联函数时,它将避免调用该函数,并将被调用函数的代码放入调用者函数中。

因此,在调用方函数(假设返回类型为整数)中,我想要类似以下内容:

ReadProcessMemory(m_processHandle, (LPVOID)addr, &bufferOfTheCaller, sizeof(int), NULL);

我对此有三个问题:

1)我们从函数返回的变量会发生什么?

不是在运行时执行变量 buffer 的声明吗?

2)在这种情况下, ReadProcessMemory 是WinAPI中的一个巨大函数,编译器是否仍可以内联此函数?

3)将成员函数保留在类定义内,并使用关键字 inline 在类定义外进行声明有什么区别?如果要使用inline关键字,是否必须将内联函数放在同一文件.h或?

3 个答案:

答案 0 :(得分:4)

请务必注意,inline关键字与内联函数调用无关。它所做的一切就是只要所有定义都相同,就可以在多个翻译单元中定义函数。

inline关键字的作用是让您在头文件中定义一个函数,该文件将包含在多个翻译单元中。这可能会给编译器提供更好的机会内联调用该函数,因为它具有在多个转换单元中可用的完整定义,但这不是命令,甚至不是您希望编译器这样做的提示。编译器将自行决定是否应该内联对任何给定函数的调用。如果确实要强制对内联函数的调用,则可以使用特定于编译器的扩展,但这不是inline关键字的作用。


这样,我将补充一点,内联函数调用的编译器根本不会改变C ++的规则。它不是文本替换,就像预处理器宏一样。编译器将弄清楚如何将逻辑从被调用函数插入到调用方中。那时,诸如C ++变量之类的东西实际上并不存在。如果您的通话看起来像这样:

int someValue = myFoo.Read(someAddress);

然后,编译器可以轻松地将其转换为如下形式:

int someValue;
ReadProcessMemory(myFoo.m_processHandle, (LPVOID)someAddress, &someValue, sizeof(int), NULL);

由于按规则。这两个代码片段都具有相同的可观察行为,因此编译器可以在它们之间自由转换。

答案 1 :(得分:3)

  

从函数返回的变量会发生什么?

它将被销毁,因为返回值已被函数调用表达式丢弃。

  

不是在运行时执行变量缓冲区的声明吗?

声明在编译时发生。

  

在这种情况下,ReadProcessMemory是WinAPI中的一个巨大函数,编译器是否应该仍然可以内联此函数?

如果编译器知道函数的定义,则它可以内联扩展它。是否应该这样做还是取决于许多因素。函数的大小是一种试探法,可能会影响编译器的选择。

  

将成员函数定义保留在类定义内部,并使用关键字inline在类定义外部进行声明之间有什么区别?

在一种情况下,定义在类内部,而在另一种情况下,定义在类外部。没有其他区别。

  

如果要使用inline关键字,是否必须将内联函数放在同一文件.h或?

  • 如果要内联定义成员函数,但要在类定义之外定义它,则必须在类定义中声明内联函数-除了隐式内联的函数模板之外。
  • 如果要在类定义中定义成员函数,则无需显式内联声明它;将会如此隐含。
  • 如果不希望内联定义函数,则必须在类定义之外定义函数,并且不能使用inline关键字。

答案 2 :(得分:2)

  

如果我没记错的话,当编译器内联函数时,它将避免调用该函数,并将被调用函数的代码放入调用者函数中。

是的,但是inline与此无关。

  

1)我们从函数返回的变量会发生什么?变量缓冲区的声明不是在运行时执行的吗?

无论是否进行内联,编译器都必须为buffer保留一些空间,通常是在堆栈上。

换句话说,没有bufferOfTheCaller。如果您的函数是内联的,则buffer将位于调用者的堆栈框架中;否则,它将被放置在被调用者的堆栈框架中。

  

2)在这种情况下,ReadProcessMemory是WinAPI中的一个巨大函数,编译器是否应该仍然可以内联此函数?

ReadProcessMemory的实现有多大无关紧要,您的代码仅对其执行函数调用,这很小。优化的编译器很可能会内联您的函数。

  

3)将成员函数定义在类定义内部并用关键字inline在类定义外部进行声明之间有什么区别?

没有区别。

  

如果要使用inline关键字,是否必须将内联函数放在同一文件.h或?

inline关键字与内联无关。如果要将函数的定义放在头文件中,则可能需要使用inline来防止重新定义错误。