在我的渲染代码中,我将字符串文字作为参数传递给我的渲染块,以便我可以在调试转储和分析中识别它们。它看起来与此相似:
// rendering client
draw.begin("east abbey foyer");
// rendering code
draw.end();
void Draw::begin(const char * debugName){
#ifdef DEBUG
// code that uses debugName
#endif
// the rest of the code doesn't use debugName at all
}
在最后的节目中,我不希望这些字符串再出现。但我也想避免在渲染客户端代码中使用宏来执行此操作;事实上,我希望渲染客户端代码能够保留字符串(在代码本身中),但实际上并没有将它们编译到最终程序中。
所以我想知道的是,如果我将draw.begin(const char*)
的代码更改为根本不使用它的参数,我的编译器是否会优化该参数并将相关成本消除(甚至可能排除在外)它来自字符串表)?
答案 0 :(得分:2)
要小心有人给你这样的问题的具体答案。您可以真正确定编译器在配置中执行的操作的唯一方法是查看结果。
最简单的方法之一是在调试器中逐步完成反汇编。
或者你可以让编译器输出一个汇编列表(参见How to view the assembly behind the code using Visual C++?)并仔细检查它到底在做什么。
答案 1 :(得分:1)
实际上,这取决于编译器是否可以访问Draw::begin()
这里有一个例子:
#include <iostream>
void do_nothing(const char* txt)
{
}
int main()
{
using namespace std;
do_nothing("hello");
return 0;
}
使用-O3编译:
的产率:
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp3:
.cfi_def_cfa_offset 16
Ltmp4:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp5:
.cfi_def_cfa_register %rbp
xorl %eax, %eax
popq %rbp
retq
.cfi_endproc
即。字符串和对do_nothing的调用完全被优化
但是,在另一个模块中定义do_nothing,我们得到:
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
leaq L_.str(%rip), %rdi
callq __Z10do_nothingPKc
xorl %eax, %eax
popq %rbp
retq
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "hello"
即。冗余加载,调用和字符串的地址被传递。
因此,如果您希望优化调试信息,那么您希望实现Draw::begin()
内联(与stl相同)。
答案 2 :(得分:0)
是的,您可以通过优化来解决问题,这可能会也可能不会起作用,具体取决于编译器的版本等。
更好的方法是明确,不是使用MACRO(上帝禁止),而是使用一个简单的函数,可以为调试目的生成所需的标记,也不对生产代码执行任何操作。
您想查看std::assert
并使用它。
答案 3 :(得分:0)
这样做的可能性取决于呼叫站点中功能的可见性。如果功能体不可见,则根本不可能进行优化。如果功能是可见的,那么是 - 你甚至不能保证会有一个函数调用!