内联与 constexpr?

发布于 2024-11-30 11:09:17 字数 299 浏览 3 评论 0原文

使用新的 C++11 标准,什么时候应该使用 inline 关键字而不是 constexpr 关键字? constexpr 关键字是否提供了对 inline 的额外优化,还是仅仅断言必须在编译时计算?

为什么在某些调用不恒定的情况下,constexpr 可以在 GCC 上工作,例如在非 constexpr 上调用 foo(x)多变的?这是 GCC 中的错误还是它实际上是标准的一部分?

With the new C++11 standard, when should I use the inline keyword over the constexpr keyword? Does the constexpr keyword offer any additional optimization over inline, or does it merely assert that things must be computed at compile-time?

Why does constexpr work on the GCC in some cases where the call is not constant, such as calling foo(x) on a non-constexpr variable? Is this a bug in the GCC or is it actually part of the standard?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

神经暖 2024-12-07 11:09:17

断言某些东西可以在编译时计算是一种非常强大的优化。

内联仅通过将函数体复制/粘贴到调用站点来删除函数调用。函数体仍然需要执行,您只需节省函数调用的开销。

但是,如果您在编译时评估相同的代码,则它在运行时是免费

inlineconstexpr 都不是主要关于优化的。 inline的主要目的是抑制one-definition-rule,以便可以在头文件中定义函数(这对模板很有用,顺便说一句,也使内联优化更容易)

constexpr 之所以存在,是因为它在元编程中很有用,顺便说一句,它可以通过将更多计算移至编译时来帮助编译器更好地优化代码。

Asserting that something can be computed at compile-time is a pretty strong kind of optimization.

Inlining merely removes a function call, by copy/pasting the function body into the call site. The function body still has to be executed, you just save the overhead of a function call.

But if you make the same code be evaluated at compile-time, it is free at runtime.

But neither inline nor constexpr are primarily about optimization. inline's main purpose is to suppress the one-definition-rule, so that functions can be defined in headers (which is useful for templates, and incidentally, also makes the inlining optimization easier)

And constexpr is there because it is useful in metaprogramming, and incidentally, it may help the compiler better optimize the code, by moving more computations to compile-time.

旧时光的容颜 2024-12-07 11:09:17

引用维基百科:

C++0x将引入关键字constexpr,它允许用户
保证函数或对象构造函数是编译时的
常数。

如果函数超短,则将其标记为内联。如果编译时需要结果,则将函数标记为 constexpr。 (模板参数或数组大小)。我相信如果需要的话,一个功能可以兼而有之。

可以调用常量表达式函数或构造函数
非 constexpr 参数。就像 constexpr 整数文字一样
分配给非 constexpr 变量,constexpr 函数也可以
使用非 constexpr 参数调用,结果存储在
非 constexpr 变量。关键字只允许可能性
当表达式的所有成员都为时,编译时恒定性
常量表达式。

因此,GCC 在这一点上并没有错。

To quote wikipedia:

C++0x will introduce the keyword constexpr, which allows the user to
guarantee that a function or object constructor is a compile-time
constant.

Mark functions inline if they are super short. Mark functions as constexpr if the results are required at compile time. (Template parameters or array sizes). I believe a function can be both if needed.

A constant expression function or constructor can be called with
non-constexpr parameters. Just as a constexpr integer literal can be
assigned to a non-constexpr variable, so too can a constexpr function
be called with non-constexpr parameters, and the results stored in
non-constexpr variables. The keyword only allows for the possibility
of compile-time constancy when all members of an expression are
constexpr.

So, GCC is not incorrect in this.

瞎闹 2024-12-07 11:09:17

虽然 inline 告诉编译器“此函数在此翻译单元中的某个位置使用,并且对其他目标文件不公开”,但编译器很可能会将函数体插入到调用者中。 constexpr 函数对编译器说“该函数没有副作用,并且不依赖于参数本身以外的前提条件”。

constexpr 变量只是说“这个变量不会改变,它的数据可以包含到代码中。”。但是,如果您在静态或非静态函数中定义 constexpr 变量,则会有所不同,例如。如果 constexpr 数组是非静态的,gcc 只是将带有硬编码 mov 指令的数据移动到堆栈上,而 static constexpr 只是将数据存储在.text 部分。

不带 capture 分配给变量的 Lambda 表达式可以是 constexpr,而不是带 capture,因为如果不带 capture,它们不需要内存来保存捕获,并且它们的工作方式就像带有重载 operator() 的空类(但它们甚至可以使用简单的一元加号将其转换为普通函数指针:+[]{})。

While inline says to the compiler "This function is used somewhere in this translation unit and is not public to other object files", it is likely that the compiler inserts the body of the function into the caller. constexpr functions say to the compiler "This function has no side effects and does not depend on preconditions other than the parameter itsself."

constexpr variables just say "This variable does not change and its data can be included into the code.". However it makes a difference if you define a constexpr variable in a function static or nonstatic, eg. if a constexpr array is nonstatic, gcc just moves the data with hardcoded mov-instructions onto the stack, while static constexpr just stores the data in the .text-section.

Lambda expressions without capture assigned to a variable can be constexpr other than with capture, because without they need no memory to save the capture and they work like an empty class with overloaded operator() (but they can even be casted to plain function pointers with a simple unary plus: +[]{}).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文