inline
关键字而不是constexpr
关键字? constexpr
关键字是否比inline
提供任何额外的优化,还是仅仅声明必须在编译时计算这些内容?为什么
constexpr
在某些情况下可以在GCC上工作,即使调用不是常量,例如对非constexpr
变量调用foo(x)
? 这是GCC中的错误还是实际上是标准的一部分?inline
关键字而不是constexpr
关键字? constexpr
关键字是否比inline
提供任何额外的优化,还是仅仅声明必须在编译时计算这些内容?constexpr
在某些情况下可以在GCC上工作,即使调用不是常量,例如对非constexpr
变量调用foo(x)
? 这是GCC中的错误还是实际上是标准的一部分?断言某些东西可以在编译时计算出来,这是一种非常强的优化。
内联只是通过将函数体复制/粘贴到调用位置中来删除函数调用。函数体仍然需要执行,您只是节省了函数调用的开销。
但是,如果您使相同的代码在编译时进行评估,则在运行时是免费的。
但是,无论是inline
还是constexpr
都不是主要关于优化的。 inline
的主要目的是抑制单一定义规则,以便可以在头文件中定义函数(这对于模板很有用,并且顺便也使内联优化更加容易)
constexpr
之所以存在是因为它在元编程中很有用,顺带地,它可以通过将更多的计算移动到编译时来帮助编译器更好地优化代码。
引用维基百科:
C++0x将引入关键字constexpr,允许用户保证函数或对象构造函数是编译时常量。
如果函数非常短,则将函数标记为inline。 如果需要在编译时必须得到结果(模板参数或数组大小),则将函数标记为constexpr。 我相信一个函数如果需要的话可以同时具备这两个标记。
常量表达式函数或构造函数可以使用非constexpr参数进行调用。 就像可以将constexpr整数文字分配给非constexpr变量一样,constexpr函数也可以使用非constexpr参数进行调用,并将结果存储在非constexpr变量中。 当表达式的所有成员都是constexpr时,该关键字仅允许编译时常数的可能性。
因此,GCC没有错误。
虽然inline
告诉编译器“这个函数在这个翻译单元中被使用,不对其他目标文件公开”,但编译器很可能会将函数体插入调用者中。constexpr
函数告诉编译器“这个函数没有副作用,也不依赖于除参数本身之外的前提条件。”
constexpr
变量只是说“这个变量不会改变,它的数据可以包含在代码中”。但是,如果您在函数静态或非静态定义一个constexpr
变量,则会有所区别。例如,如果constexpr
数组是非静态的,则gcc仅使用硬编码的mov
指令将数据移动到堆栈上,而static constexpr
则将数据存储在.text
部分中。
没有捕获的Lambda表达式分配给变量可以是constexpr
,而有捕获的则不行,因为没有捕获时它们不需要保存捕获的内存,并且它们的工作方式类似于重载了operator()
的空类(但它们甚至可以通过简单的一元加号转换为普通函数指针:+[]{}
)。
constexpr
函数未在需要常量表达式的上下文中使用时,编译器没有义务在编译时计算表达式。 - ildjarninline
不是主要用于优化的说法。如果我没记错,在头文件中定义的函数默认是内联的,尽管像一直以来的情况一样,这只是一个编译器提示。只要你有适当的头文件保护措施,那么ODR就不是真正相关的问题了。但我愿意在这里接受教育 :-) - boycyinline
对于模板很有用,但实际上并不是这样的。函数模板和类内定义的成员函数会自动被视为具有inline
关键字。它对于在多个翻译单元中定义的自由函数(通常由于在头文件中定义并包含在不同的TU中)非常有用,并通过告诉链接器在链接时丢弃所有但一个定义来避免链接器错误。 - SirGuy