用 C++ 编写多级内联函数是个好主意吗?
Is it good idea to write multi level inline functions in C++?
像这样的代码被认为是一种不好的做法吗?
如果是这样,当 func1
重复 func2
的行为并且我需要同时存在这两个函数时我应该怎么做(这不是被认为是代码冗余)?!
UPD:对不起,我的插图不好,我会尝试更清楚地解释这个问题。
我想问的是:
我正在尝试设计一个优化的 class,它大量调用两种方法 func1
和 func2
,func1
的实现使用 func2
,我想要这两种方法调用尽可能内联,所以像这段代码一样从 func1
调用 func2
还是独立实现两者更好。
inline int func2(int x) {
return x * (x + 2);
}
inline int func1(int x) {
return x * (x + 1) * func2(x + 2);
}
如果避免多次编写相同的代码,则编写多个小函数是可以的。有些人可能会争辩说,太多的小函数会使代码难以阅读,这是一个见仁见智的问题。
如果您担心性能,编译器会在认为有帮助的情况下内联,在证明存在问题之前您不应该担心它。请参阅 this question 过早优化。
一个函数调用另一个函数没有问题。如果你对它们进行采样,你会发现真实的程序比 2 个调用更深入。
就内联而言,这也没有问题。优化编译器通常会内联 func2
(假设其定义可见并且启用了优化)。许多常见的编译器和优化器都擅长内联。他们通常知道什么时候内联什么时候不内联——所有这一切都不需要您的帮助。
编写小函数并不是一个坏习惯。清晰度和意图通常比微优化更重要。在典型情况下,您的示例没有任何问题。
如果它有助于提高代码的可读性,那么可以。您几乎应该总是以代码的可读性为目标。不要忘记正确命名您的功能,以便其他人可以轻松理解该功能的作用。其他人我指的是几周或几个月后的你。正如他们所说,您只写一次代码,但要多次阅读。
至于性能,现代编译器知道什么时候内联函数,你不应该担心它。在真正重要的情况下,您只需使用探查器来查找 hostspot 并最终更改它。但它发生的次数比你想象的要少得多。您几乎总能找到优化代码的更好方法。
如果两者都在同一范围内实现,编译甚至可以在没有 inline
的情况下进行一些代数优化。前段时间,当我看到编译器有时会用简单的目标函数调用替换大而复杂的结构时,我感到非常惊讶(有点为 d3d api 携带参数)。所以,如果您担心性能,那就不要...至少您的应用程序基准测试非常糟糕。
另一方面,这都是关于关系的:如果 func1 与 func2 没有 逻辑上 关系,只有 code\math 有点相同,而不是将 func2 复制到 func1 中.为什么?因为 func2 可能会改变,但你忘记了 func1 并破坏了它,因为它们不是由内部域逻辑相关的。
更新后的更新
如果所有关于速度和他们的只是数学,而不是在 func1 中编写完全优化的表达式并且不依赖编译器。但前提是你真的知道性能是第一位的。
像这样的代码被认为是一种不好的做法吗?
如果是这样,当 func1
重复 func2
的行为并且我需要同时存在这两个函数时我应该怎么做(这不是被认为是代码冗余)?!
UPD:对不起,我的插图不好,我会尝试更清楚地解释这个问题。
我想问的是:
我正在尝试设计一个优化的 class,它大量调用两种方法 func1
和 func2
,func1
的实现使用 func2
,我想要这两种方法调用尽可能内联,所以像这段代码一样从 func1
调用 func2
还是独立实现两者更好。
inline int func2(int x) {
return x * (x + 2);
}
inline int func1(int x) {
return x * (x + 1) * func2(x + 2);
}
如果避免多次编写相同的代码,则编写多个小函数是可以的。有些人可能会争辩说,太多的小函数会使代码难以阅读,这是一个见仁见智的问题。
如果您担心性能,编译器会在认为有帮助的情况下内联,在证明存在问题之前您不应该担心它。请参阅 this question 过早优化。
一个函数调用另一个函数没有问题。如果你对它们进行采样,你会发现真实的程序比 2 个调用更深入。
就内联而言,这也没有问题。优化编译器通常会内联 func2
(假设其定义可见并且启用了优化)。许多常见的编译器和优化器都擅长内联。他们通常知道什么时候内联什么时候不内联——所有这一切都不需要您的帮助。
编写小函数并不是一个坏习惯。清晰度和意图通常比微优化更重要。在典型情况下,您的示例没有任何问题。
如果它有助于提高代码的可读性,那么可以。您几乎应该总是以代码的可读性为目标。不要忘记正确命名您的功能,以便其他人可以轻松理解该功能的作用。其他人我指的是几周或几个月后的你。正如他们所说,您只写一次代码,但要多次阅读。
至于性能,现代编译器知道什么时候内联函数,你不应该担心它。在真正重要的情况下,您只需使用探查器来查找 hostspot 并最终更改它。但它发生的次数比你想象的要少得多。您几乎总能找到优化代码的更好方法。
如果两者都在同一范围内实现,编译甚至可以在没有 inline
的情况下进行一些代数优化。前段时间,当我看到编译器有时会用简单的目标函数调用替换大而复杂的结构时,我感到非常惊讶(有点为 d3d api 携带参数)。所以,如果您担心性能,那就不要...至少您的应用程序基准测试非常糟糕。
另一方面,这都是关于关系的:如果 func1 与 func2 没有 逻辑上 关系,只有 code\math 有点相同,而不是将 func2 复制到 func1 中.为什么?因为 func2 可能会改变,但你忘记了 func1 并破坏了它,因为它们不是由内部域逻辑相关的。
更新后的更新
如果所有关于速度和他们的只是数学,而不是在 func1 中编写完全优化的表达式并且不依赖编译器。但前提是你真的知道性能是第一位的。