c – 为什么要访问一个类的私有变量,就像访问一个struct的变量一样有效?

前端之家收集整理的这篇文章主要介绍了c – 为什么要访问一个类的私有变量,就像访问一个struct的变量一样有效?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我实现了一些主要数据结构是一个树的算法.我使用一个类来表示一个节点和一个类来表示一个树.因为节点得到更新很多,所以我打电话给很多设置者和getter.

因为我听到很多次函数调用很昂贵,我在想,也许如果我使用结构体代表节点和树,这将使我的算法在实践中更有效率.

在这样做之前,我决定进行一个小实验,看看是否真的是这样.

我创建了一个有一个私有变量,一个setter和一个getter的类.此外,我创建了一个也有一个变量的结构,没有setter / getter,因为我们可以通过调用struct.varName更新变量.结果如下:

运行次数就是我们称之为setter / getter的次数.以下是实验的代码

#include <iostream>
#include <fstream>

#define BILLION  1000000000LL

using namespace std;

class foo{
private:
    int a;
public:

    void set(int newA){
        a = newA;
    }
    int get(){
        return a;
    }
};

struct bar{
    int a;
};

timespec startT,endT;

void startTimer(){
    clock_gettime(CLOCK_PROCESS_cpuTIME_ID,&startT);
}

double endTimer(){
    clock_gettime(CLOCK_PROCESS_cpuTIME_ID,&endT);
    return endT.tv_sec * BILLION + endT.tv_nsec - (startT.tv_sec * BILLION + startT.tv_nsec);
}


int main() {

    int runs = 10000000;
    int startRun = 10000;
    int step = 10000;
    int iterations = 10;
    int res = 0;
    foo f;
    ofstream fout;
    fout.open("stats.txt",ios_base::out);
    fout<<"alg\truns\ttime"<<endl;
    cout<<"First experiment progress: "<<endl;
    int cnt = 0;
    for(int run = startRun; run <= runs; run += step){
        double curTime = 0.0;
        for(int iter = 0; iter < iterations; iter++) {
            startTimer();
            for (int i = 1; i <= run; i++) {
                f.set(i);
                res += f.get();
            }
            curTime += endTimer()/iterations;
            cnt++;
            if(cnt%10 == 0)
                cout<<cnt/(((double)runs-startRun+1)/step*iterations)*100<<"%\r";
        }
        fout<<"class\t"<<run<<"\t"<<curTime/BILLION<<endl;
    }

    int res2 = 0;
    bar b;
    cout<<"Second experiment progress: "<<endl;
    cnt = 0;
    for(int run = startRun; run <= runs; run += step){
        double curTime = 0.0;
        for(int iter = 0; iter < iterations; iter++) {
            startTimer();
            for (int i = 1; i <= run; i++) {
                b.a = i;
                res2 += b.a;
            }
            curTime += endTimer()/iterations;
            cnt++;
            if(cnt%10 == 0)
                cout<<cnt/(((double)runs-startRun+1)/step*iterations)*100<<"%\r";
        }
        fout<<"struct\t"<<run<<"\t"<<curTime/BILLION<<endl;
    }

    fout.close();
    cout<<res<<endl;
    cout<<res2<<endl;

    return 0;
}

我不明白为什么我得到这个行为.我以为功能调用更昂贵?

编辑:我没有-O3重新运行相同的实验

编辑:这是非常令人惊讶的,通过在一个单独的文件foo.h中声明类,在foo.cpp中实现getters / setters并运行-O3,似乎该类变得更加低效.

解决方法

I have heard many times that function calls are expensive.

这是1970年的任何机会吗?

编译器很聪明很聪明.他们会产生最佳的程序,他们可以提供您的源代码,除非你做的事情非常奇怪,否则这些设计变更不太可能产生很大的影响(如果有的话).

最值得注意的是,在大多数情况下,一个简单的getter / setter甚至可以被完全嵌入(除非你在做一些奇怪的事情),使你的两个程序有效地一次编译!您可以在图表上看到此结果.

同时,使用struct替换类的具体变化对性能没有影响 – 两个关键字都定义了一个类.

I don’t understand why I get this behavIoUr. I thought that function calls were more expensive?

看,这就是为什么我们不会过早地优化.编写清晰,易于阅读的代码,无需任何技巧,让编译器保持休息.这是它的工作,它通常是非常好的.

猜你在找的C&C++相关文章