C++ 内联这个函数,有意义吗?

C++ 内联这个函数,有意义吗?,c++,templates,winapi,inline,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; }

我有下一个成员功能:

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;
}
关于这一点,我有三个问题:

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

2在本例中,ReadProcessMemory是WinAPI中的一个巨大函数,编译器是否仍然能够内联此函数

3将成员函数保留在类定义内部和在类定义外部用关键字inline声明它之间有什么区别?如果我想使用内联关键字,我必须将内联函数放在同一个文件中。h还是

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

是的,但内联与此无关

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

编译器,无论是否内联,都必须为缓冲区保留一些空间,通常是在堆栈上

换句话说,并没有调用者的缓冲区。如果函数是内联的,则缓冲区将位于调用方的堆栈帧中;否则,它将被放入被调用方的堆栈框架中

2在本例中,ReadProcessMemory是WinAPI中的一个巨大函数,编译器是否仍然能够内联此函数

无论ReadProcessMemory的实现有多大,您的代码只是对它执行一个函数调用,这很小。优化编译器可能会内联您的函数

3将成员函数保留在类定义内部和在类定义外部用关键字inline声明它之间有什么区别

没有区别

如果我想使用内联关键字,我必须将内联函数放在同一个文件中。h还是

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

我们从函数返回的变量会发生什么情况

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

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

声明发生在编译时

在这种情况下,ReadProcessMemory是WinAPI中的一个巨大函数,编译器是否仍然能够内联此函数

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

将成员函数保留在类定义内部和在类定义外部用关键字inline声明它之间有什么区别

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

如果我想使用内联关键字,我必须将内联函数放在同一个文件中。h还是

如果要内联定义成员函数,但要在类定义之外定义它,则必须在类定义内内联声明函数-函数模板除外,它是隐式内联的。 如果要在类定义中定义成员函数,则不需要显式地内联声明它;这将是如此含蓄。 如果不希望定义函数内联,则必须在类定义之外定义函数,并且不得使用内联关键字。
需要注意的是,inline关键字与函数的内联调用无关。它所做的只是允许在多个翻译单元中定义函数,只要所有定义都相同

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

<> P>这是一个附加的函数,我将补充说明,编译器内联函数调用不会改变C++的规则。它不像预处理器宏那样是文本替换。编译器将找出如何将被调用函数中的逻辑插入调用方。这时,像C++变量之类的东西就不存在了。如果您的电话看起来像这样:

int someValue = myFoo.Read(someAddress);
int someValue;
ReadProcessMemory(myFoo.m_processHandle, (LPVOID)someAddress, &someValue, sizeof(int), NULL);
然后公司 mpiler可以轻松地将其转换为以下内容:

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

由于“似乎”规则。这两个代码段产生相同的可观察行为,因此编译器可以在它们之间自由转换。

内联是完全冗余的。函数位于标头中的类声明中,因此它是隐式内联的。除此之外,内联并不意味着你认为它能做什么。它与函数的实际内联调用无关,编译器是否会这样做取决于它自己的启发式算法。它只与链接和ODR有关。@JesperJuhl是的,内联是多余的,但因为它是一个模板。它不在类定义前缀Foo::中声明。我同意其余的观点,没有任何作用。这是一个函数模板。所以,无论ReadProcessMemory有多大?事实上,我将经常使用这个函数Read,因此避免调用,无论它是否很小,都应该更好。@EduardoG不仅这无关紧要,您的编译器甚至不知道ReadProcessMemory有多大,因为它是对外部库的调用。@edu:ReadProcessMemory本身的成本非常高。尝试优化call指令永远不会产生明显的甚至是可测量的差异。如果您需要优化性能,请首先进行测量。使用分析器。