内联传递引用函数是否仍然创建引用变量?
Do inlined pass-by-reference functions still create reference variables?
我正在编写一个具有一些状态变量的循环。
int MyFunc(){
int state_variable_1 = 0;
int state_variable_2 = 12;
while(state_variable_1 != state_variable_2){
BodyOfWhileLoop(state_variable_1, state_variable_2);
}
}
如您所见,我将 while 循环的主体写在一个单独的函数中,BodyOfWhileLoop
。这是为了保持代码干净并有助于调试。
BodyOfWhileLoop
将需要修改 state_variable_1
和 state_variable_2
。我可以通过引用传递这些,例如,
void BodyOfWhileLoop(int& state_variable_1, int& state_variable_2);
这在功能上正是我想要的,但是,在函数体中每次使用状态变量都需要取消引用(我相信)。我可以这样做:
void BodyOfWhileLoop(int& state_variable_1_ref, int& state_variable_2_ref){
int state_variable_1_copy = state_variable_1_ref;
int state_variable_2_copy = state_variable_2_ref;
// Do stuff with state variables
state_variable_1_ref = state_variable_1_copy;
state_variable_2_ref = state_variable_2_copy;
}
我认为有两件事是正确的:
- 复制状态变量会消耗内存,因为您为副本分配了 space。
- 不复制状态变量会花费时间,因为每次访问状态变量时
BodyOfWhileLoop
的主体中都会有一个额外的取消引用。
所以我有两个问题:
- 如果编译器内联
BodyOfWhileLoop
,它是否仍会创建 state_variable_1_ref
和 state_variable_2_ref
(需要取消引用才能访问 int
)?访问 state_variable_1
的费用是否与在 MyFunc
内访问的费用相同?
- 有没有我没见过的替代解决方案?
不,他们没有。示范:https://godbolt.org/z/qc1ne7ezM.
引用通常在幕后实现为指针(尽管它们不一定是)。内联函数后,编译器将消除间接寻址。在 LLVM 中,此优化作为 SROA.
的一部分执行
任何只有一个调用点的函数都应该被优化器内联,但请注意,如果一个函数有外部链接,编译器可能不会内联它:它可以在其他翻译单元中使用,所以编译器不知道它是唯一的用过一次。为避免这种情况,将其标记为static
或inline
,或使用link-time优化。
C++ 标准不要求 C++ 编译器以任何特定方式生成编译代码。 C++ 标准指定了 well-formed C++ 代码的结果,而编译器如何去做完全取决于编译器。没有两个 C++ 编译器是相同的,不同的 C++ 编译器可能会采用不同的方法并从中等复杂度的 C++ 程序中生成不同的编译代码。
此外,越来越多的 C++ 编译器已经发展到实现新的 link-time 优化技术,这些技术将可能的优化范围扩展到传统上可能的范围之外,到目前为止。
通常,允许 C++ 编译器实现任何没有明显效果的优化。如果您的 C++ 编译器可以证明您所考虑的优化没有明显的效果,那么您的 C++ 编译器可以(但没有义务)实现它。
编译器是否最终进行此优化或任何其他优化完全取决于编译器,最终结果也可能因编译选项而异。所以,对于这类问题没有明确的答案,除了编译代码然后检查生成的编译机器代码以查看您的编译器目录。
我正在编写一个具有一些状态变量的循环。
int MyFunc(){
int state_variable_1 = 0;
int state_variable_2 = 12;
while(state_variable_1 != state_variable_2){
BodyOfWhileLoop(state_variable_1, state_variable_2);
}
}
如您所见,我将 while 循环的主体写在一个单独的函数中,BodyOfWhileLoop
。这是为了保持代码干净并有助于调试。
BodyOfWhileLoop
将需要修改 state_variable_1
和 state_variable_2
。我可以通过引用传递这些,例如,
void BodyOfWhileLoop(int& state_variable_1, int& state_variable_2);
这在功能上正是我想要的,但是,在函数体中每次使用状态变量都需要取消引用(我相信)。我可以这样做:
void BodyOfWhileLoop(int& state_variable_1_ref, int& state_variable_2_ref){
int state_variable_1_copy = state_variable_1_ref;
int state_variable_2_copy = state_variable_2_ref;
// Do stuff with state variables
state_variable_1_ref = state_variable_1_copy;
state_variable_2_ref = state_variable_2_copy;
}
我认为有两件事是正确的:
- 复制状态变量会消耗内存,因为您为副本分配了 space。
- 不复制状态变量会花费时间,因为每次访问状态变量时
BodyOfWhileLoop
的主体中都会有一个额外的取消引用。
所以我有两个问题:
- 如果编译器内联
BodyOfWhileLoop
,它是否仍会创建state_variable_1_ref
和state_variable_2_ref
(需要取消引用才能访问int
)?访问state_variable_1
的费用是否与在MyFunc
内访问的费用相同? - 有没有我没见过的替代解决方案?
不,他们没有。示范:https://godbolt.org/z/qc1ne7ezM.
引用通常在幕后实现为指针(尽管它们不一定是)。内联函数后,编译器将消除间接寻址。在 LLVM 中,此优化作为 SROA.
的一部分执行任何只有一个调用点的函数都应该被优化器内联,但请注意,如果一个函数有外部链接,编译器可能不会内联它:它可以在其他翻译单元中使用,所以编译器不知道它是唯一的用过一次。为避免这种情况,将其标记为static
或inline
,或使用link-time优化。
C++ 标准不要求 C++ 编译器以任何特定方式生成编译代码。 C++ 标准指定了 well-formed C++ 代码的结果,而编译器如何去做完全取决于编译器。没有两个 C++ 编译器是相同的,不同的 C++ 编译器可能会采用不同的方法并从中等复杂度的 C++ 程序中生成不同的编译代码。
此外,越来越多的 C++ 编译器已经发展到实现新的 link-time 优化技术,这些技术将可能的优化范围扩展到传统上可能的范围之外,到目前为止。
通常,允许 C++ 编译器实现任何没有明显效果的优化。如果您的 C++ 编译器可以证明您所考虑的优化没有明显的效果,那么您的 C++ 编译器可以(但没有义务)实现它。
编译器是否最终进行此优化或任何其他优化完全取决于编译器,最终结果也可能因编译选项而异。所以,对于这类问题没有明确的答案,除了编译代码然后检查生成的编译机器代码以查看您的编译器目录。