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替换类的具体变化对性能没有影响 – 两个关键字都定义了一个类.
看,这就是为什么我们不会过早地优化.编写清晰,易于阅读的代码,无需任何技巧,让编译器保持休息.这是它的工作,它通常是非常好的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
