这个指针和性能惩罚

  • 本文关键字:性能 惩罚 指针 c++
  • 更新时间 :
  • 英文 :

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指针来调用成员函数,但是类似C的do_something不需要这个指针,这个指针会带来吗与类C函数相比,性能会受到一些损失吗?

我没有做任何微观优化的意思,因为这会给我带来很多时间总是不能给我带来好的结果,我总是遵循"衡量,不要思考"的规则。出于好奇,我想知道这个指针是否会给表现带来惩罚。

这取决于具体情况,但通常情况下,如果启用了优化,它不会比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

请注意,它完全优化了DummyglobalDoStuff(),只是用globalDoStuff()的主体替换了它。globalDoStuff()从未被调用,也从未构造过Dummy。相反,编译器/优化器用两个系统调用来替换该代码,以直接打印出"Hello world!n"。教训是编译器和优化器非常聪明,一般来说,你不会为不需要的东西付费。

另一方面,假设您有一个成员函数,它操纵Dummy的成员变量。你可能会认为,与C函数相比,这是一个惩罚,对吧?可能不会,因为C函数需要一个指向要修改的对象的指针,仔细想想,这正是this指针的起点。

因此,与C相比,C++中的this通常不会额外付费。虚拟函数可能会有(小)损失,因为它必须查找要调用的正确函数,但我们在这里考虑的不是这种情况。

如果你不在编译器中启用优化,那么是的,当然,可能会受到惩罚,但是。。。为什么要比较未优化的代码?

#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;
}

平均运行10次gcc版本4.3.5(Debian 4.3.5-4),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

最新更新