我写了一些假代码,可以解释我在实际应用程序中发现的问题(Arduino 1.6 - https://github.com/maciejmiklas/LEDDisplay):
Display.h:
class Display {
public:
void testRef();
void testVal();
private:
typedef struct {
uint8_t xOnFirstKit;
uint8_t yOnFirstKit;
uint8_t xRelKit;
uint8_t yRelKit;
uint8_t xRelKitSize;
uint8_t yRelKitSize;
uint8_t xDataBytes;
uint8_t xKit;
uint8_t yKit;
uint8_t xOnKit;
uint8_t yOnKit;
uint8_t xOnKitSize;
uint8_t yOnKitSize;
uint8_t xOnScreenIdx;
uint8_t yOnScreenIdx;
uint8_t yDataIdx;
} KitData;
inline void paintOnKitRef(KitData *kd);
inline void paintOnKitVal(KitData kd);
}
Display.cpp:
#include "Display.h"
void Display::testRef(){
KitData *kd = ....
for(int i = 0 ; i < 5000 ; i++){
paintOnKitRef(kd);
....
}
}
void Display::testVal(){
KitData *kd = ....
for(int i = 0 ; i < 5000 ; i++){
paintOnKitVal(*kd);
....
}
}
inline void Display::paintOnKitRef(KitData *kd){
for(int i = 0 ; i < 100 ; i++){
kd->yDataIdx++;
kd->yOnScreenIdx++;
.....
}
}
inline void Display::paintOnKitVal(KitData kd){
for(int i = 0 ; i < 100 ; i++){
kd.yDataIdx++;
kd.yOnScreenIdx++;
.....
}
}
Run Code Online (Sandbox Code Playgroud)
我有结构:KitData大于16个字节,所以我决定用指针而不是值传递它 - 它按预期工作.
我已经测量了执行时间,看起来像传递值(testVal())比传递引用(testRef())要快30%.
这是正常的吗?
编辑:
上面的代码只是一个伪代码 - 在我真正的测试方法中:paintOnKitVal()并且paintOnKitRef()包含执行许多操作和其他方法的实际代码.这两种方法也做同样的事情 - 唯一的区别是访问方式(通过kd指针或点表示法).
这是真正的测试类:https://github.com/maciejmiklas/LEDDisplay/blob/callByPoint/Display.cpp
paint(...)- 这将使用第211行中的call-by-pointer这部分代码绝对没有任何内容,优化器会识别出:
inline void Display::paintOnKitVal(KitData kd){
for(int i = 0 ; i < 100 ; i++){
kd.yDataIdx++;
kd.yOnScreenIdx++;
}
}
Run Code Online (Sandbox Code Playgroud)
你想象你测试了pass by value的性能.但是你真的测试了编译器识别代码什么都不做的事实的能力.
当您通过指针(C程序员可能通过引用调用"但C++程序员不会"通过引用)时,单独的函数不能说什么也不做.优化器需要更广泛地理解整个程序发现缺乏效果.