void do_something() {....}
struct dummy
{
//even I dont call this, compiler will call it fall me, they need it
void call_do_something() { this->do_something_member(); }
void do_something() {....}
};
根据我所知,C ++中的每个类或结构都将是隐含的 当您要访问数据成员或成员函数时,此指针 这个类会不会给C ++带来性能损失?
我的意思是
int main()
{
do_something(); //don't need this pointer
dummy().call_do_something(); //assume the inline is prefect
return 0;
}
call_do_something需要一个this指针来调用成员函数,但是 像do_something这样的C不需要这个指针,这个指针会带来 与C like函数相比,会有一些性能损失吗?
我没有任何意义可以做任何微优化,因为它会给我带来太多 时间但总是不给我带来好结果,我总是遵循“衡量,不思考”的规则。 我想知道这个指针会因为好奇而带来性能损失。
答案 0 :(得分:8)
取决于具体情况,但通常情况下,如果您已启用优化,则它不应该比C版本贵。您真正“支付”this
和其他功能的唯一时间是您使用继承和虚拟功能。除此之外,编译器足够聪明,不会在你没有使用它的函数中浪费时间this
。请考虑以下事项:
#include <iostream>
void globalDoStuff()
{
std::cout << "Hello world!\n";
}
struct Dummy
{
void doStuff() { callGlobalDoStuff(); }
void callGlobalDoStuff() { globalDoStuff(); }
};
int main()
{
globalDoStuff();
Dummy d;
d.doStuff();
}
使用GCC优化级别O3
编译,我得到以下反汇编(削减额外的垃圾并只显示main()
):
_main:
0000000100000dd0 pushq %rbp
0000000100000dd1 movq %rsp,%rbp
0000000100000dd4 pushq %r14
0000000100000dd6 pushq %rbx
0000000100000dd7 movq 0x0000025a(%rip),%rbx
0000000100000dde leaq 0x000000d1(%rip),%r14
0000000100000de5 movq %rbx,%rdi
0000000100000de8 movq %r14,%rsi
0000000100000deb callq 0x100000e62 # bypasses globalDoStuff() and just prints "Hello world!\n"
0000000100000df0 movq %rbx,%rdi
0000000100000df3 movq %r14,%rsi
0000000100000df6 callq 0x100000e62 # bypasses globalDoStuff() and just prints "Hello world!\n"
0000000100000dfb xorl %eax,%eax
0000000100000dfd popq %rbx
0000000100000dfe popq %r14
0000000100000e00 popq %rbp
0000000100000e01 ret
请注意,它已完全优化了Dummy
和globalDoStuff()
,并将其替换为globalDoStuff()
的正文。甚至都没有调用globalDoStuff()
,也没有构建Dummy
。相反,编译器/优化器用两个系统调用替换该代码以直接打印出"Hello world!\n"
。经验教训是编译器和优化器非常聪明,一般情况下你不会为不需要的东西买单。
另一方面,假设您有一个成员函数来操作Dummy
的成员变量。你可能会认为这与C函数相比有所作为,对吗?可能不是,因为C函数需要一个指向要修改的对象的指针,当你想到它时,它正是this
指针的开头。
所以一般来说,与C相比,你不会为C ++中的this
支付额外的费用。虚拟函数可能会有(小)惩罚,因为它必须查找正确的函数来调用,但事实并非如此我们在这里考虑。
如果你没有在你的编译器中启用优化,那么,确定,可能会有一个惩罚,但是......为什么你要比较非优化代码?
答案 1 :(得分:3)
#include <iostream>
#include <stdint.h>
#include <limits.h>
struct Dummy {
uint32_t counter;
Dummy(): counter(0) {}
void do_something() {
counter++;
}
};
uint32_t counter = 0;
void do_something() { counter++; }
int main(int argc, char **argv) {
Dummy dummy;
if (argc == 1) {
for (int i = 0; i < INT_MAX - 1; i++) {
for (int j = 0; j < 1; j++) {
do_something();
}
}
} else {
for (int i = 0; i < INT_MAX - 1; i++) {
for (int j = 0; j < 1; j++) {
dummy.do_something();
}
}
counter = dummy.counter;
}
std::cout << counter << std::endl;
return 0;
}
gcc版本4.3.5(Debian 4.3.5-4)平均10次运行,64位,没有任何标志:
全局计数器:0m15.062s
带虚拟对象的:0m21.259s
如果我将此代码修改为Lyth建议:
#include <iostream>
#include <stdint.h>
#include <limits.h>
uint32_t counter = 0;
struct Dummy {
void do_something() {
counter++;
}
};
void do_something() { counter++; }
int main(int argc, char **argv) {
Dummy dummy;
if (argc == 1) {
for (int i = 0; i < INT_MAX; i++) {
do_something();
}
} else {
for (int i = 0; i < INT_MAX; i++) {
dummy.do_something();
}
}
std::cout << counter << std::endl;
return 0;
}
然后,奇怪的是,
全局计数器:0m12.062s
带虚拟对象的:0m11.860s