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<<"algtrunsttime"<<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<<"classt"<<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<<"structt"<<run<<"t"<<curTime/BILLION<<endl; } fout.close(); cout<<res<<endl; cout<<res2<<endl; return 0; } 我不明白为什么我得到这个行为.我以为功能调用更昂贵? 编辑:我没有-O3重新运行相同的实验 编辑:这是非常令人惊讶的,通过在一个单独的文件foo.h中声明类,在foo.cpp中实现getters / setters并运行-O3,似乎该类变得更加低效. 解决方法
这是1970年的任何机会吗? 编译器很聪明很聪明.他们会产生最佳的程序,他们可以提供您的源代码,除非你做的事情非常奇怪,否则这些设计变更不太可能产生很大的影响(如果有的话). 最值得注意的是,在大多数情况下,一个简单的getter / setter甚至可以被完全嵌入(除非你在做一些奇怪的事情),使你的两个程序有效地一次编译!您可以在图表上看到此结果. 同时,使用struct替换类的具体变化对性能没有影响 – 两个关键字都定义了一个类.
看,这就是为什么我们不会过早地优化.编写清晰,易于阅读的代码,无需任何技巧,让编译器保持休息.这是它的工作,它通常是非常好的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |