我正在构建一个类似于C库的C ++接口:
extern "C" {
typedef struct CFooStruct *CFoo;
int CFoo_getLength(CFoo);
// other functions
}
目前我有
class MyFoo {
CFoo foo;
int len;
public:
MyFoo(CFoo foo) : foo(foo), len(CFoo_getLength(foo)) { }
int length() const { return len; } // inline function
// other functions
};
在构造函数中检索长度并缓存,以便可以在紧密循环中重复调用MyFoo::length()
而不会降低性能。
当直接使用C接口时,如果需要,可以手动检索一次的长度,然后重复使用它。如果不需要CFoo
的长度,那么我们就永远不会致电CFoo_getLength()
。
C ++接口意味着更易于使用,让用户只需使用length()
而无需考虑性能。上述实现的缺点是,总是在创建每个CFoo_getLength()
对象期间调用MyFoo
,无论它是否实际在程序中使用。
尽管MyFoo
的所有成员函数都是内联的,但我相信编译器不会优化对CFoo_getLength()
的调用,因为它无法知道此函数没有副作用。< / p>
问题:有没有办法实现这一点,只有在程序中实际使用了长度时才会调用CFoo_getLength()
? (并且对于MyFoo
对象,它永远不会被调用多次?)是否有办法允许编译器优化CFoo_getLength()
调用(如果它足够聪明,可以推断它是不需要)?
一种方法是在类中有一个布尔标志,指示是否已经检索了长度:
class MyFoo2 {
CFoo foo;
bool lenKnown = false;
int len;
public:
MyFoo2(CFoo foo) : foo(foo) { }
int length() {
if (!lenKnown) {
len = CFoo_getLength(foo);
lenKnown = true;
}
return len;
}
};
但这是一个运行时解决方案,它使MyFoo
更大,并导致MyFoo::length()
内的额外计算。我想知道是否有编译时解决方案。
答案 0 :(得分:3)
您可以应用pure
函数属性将CFoo_getLength
标记为纯:
__attribute__ ((pure))
int CFoo_getLength(CFoo);
正如您所发现的,以及我的C ++ - 没有经验的惊喜,它允许gcc和clang优化您的原始代码。尼斯!