我可以完全停止使用"inline"吗?
Can I stop using "inline" altogether?
因为它完全取决于编译器是否内联我的函数,我可以完全停止使用这个关键字(假设它将内联一切,无论如何)?
您可以停止使用inline
作为优化技术。
inline
基本上只在您希望ODR(一个定义规则)不应用时才有用。简而言之,您可以将函数标记为inline
,并直接在一个头文件中提供它们的定义,然后由多个翻译单元导入,而不会引起链接器的抱怨:
foo.hpp
inline int foo() { return 42; }
foo.cpp
#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline,
// because its definition is imported also in main.cpp
void bar()
{
int x = foo();
}
main.cpp
#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline,
// because its definition is imported also in foo.cpp
int main()
{
std::cout << foo();
}
inline
关键字的存在(同样,它不能保证编译器将执行内联)确保链接器将合并那些定义。
当然,为了使这个合并操作有意义,所有标记为inline
的函数的定义(最终成为几个不同翻译单元的一部分)必须是相同的。如果不是这种情况,您的程序有未定义行为并且不需要诊断-这意味着您的编译器/链接器不需要检测这种不一致并告诉您出了问题!
根据c++ 11标准第3.2/4段,实际上:
每个程序应该只包含一个非内联函数或变量的定义在那个项目中;不需要诊断。定义可以显式地出现在程序中,可以找到它在标准库或用户定义库中,或者(适当时)隐式定义(参见12.1,12.4和12.8)。内联函数应在每一个使用该函数的翻译单元中定义。
注意,您可以将相同的函数标记为inline
,并在不同的翻译单位中字面上定义两次,只要这些定义相同就可以:
foo.cpp
inline int foo() // Has the same body in main.cpp, no problem!
{
return 42;
}
main.cpp
inline int foo() // Has the same body in foo.cpp, no problem!
{
return 42;
}
int main()
{
std::cout << foo();
}
然而,如果这两个定义不同,您将在代码中注入UB,如下面的示例所示:
foo.cpp
inline int foo()
{
return 42; // <== WATCH OUT! Different body in main.cpp
}
main.cpp
inline int foo()
{
return -42; // <== WATCH OUT! Different body in foo.cpp
}
int main()
{
std::cout << foo();
}
这就是为什么当你在通常的 #include
d头文件中直接提供函数定义时,通常将函数标记为inline
。
还要注意,定义直接内联在类定义中的类成员函数被自动标记为inline
。
取决于使用inline
的目的。
常见的(错误的)概念:
inline
只是一个编译器可能遵守也可能不遵守的建议。一个好的编译器无论如何都会做需要做的事情。
然而,真相:
inline
通常向实现表明,在调用点对函数体进行内联替换比通常的函数调用机制更可取。实现不需要在调用点执行此内联替换;然而,即使省略了inline
的替换,也遵循inline
的其他规则(特别是w.r.t One Definition Rule)。
所以如果你使用的目的是优化答案是:
YES,您可以停止使用
inline
。大多数现代编译器都可以很好地为您完成。
但是,如果您使用inline
的目的是允许您通过一个定义规则并在头文件中定义函数体而不破坏ODR,那么答案是:
NO,您需要显式地将函数标记为
inline
,以便能够绕过ODR。
注意:在类体中定义的成员函数是隐式的inline
,但这并不适用于自由函数。
- 函数向量_指针有不同的原型,我可以构建一个吗
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 为什么我可以通过引用修改常量返回
- 我可以在 C++ 中的函数体之外进行操作吗?
- 我可以重新分配/覆盖std::字符串吗
- C++-我可以创建另一个类的成员并在构造函数中使用它吗
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 为什么我可以使用比分配的内存更多的内存
- 在一个读写器队列中,我可以用volatile替换原子吗
- 我可以把基础班提升为儿童班吗
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 我可以使用什么来停止循环而不是"返回 0"?
- 我可以使用反向迭代器作为ForwardIt吗
- 我可以创建一个包含两个变量的 for 循环,但时间复杂度仍然为 O(n) 吗?
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- 我可以完全停止使用"inline"吗?