有没有办法让编译器优化对外部函数的多次调用?
Is there a way to allow compiler to optimize away multiple calls to an extern function?
我正在构建一个 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()
而无需考虑性能。上述实现的缺点是它 总是 在创建每个 MyFoo
对象的过程中调用 CFoo_getLength()
,而不管它是否会在程序中实际使用.
即使 MyFoo
的所有成员函数都是内联的,我相信编译器不会优化掉对 CFoo_getLength()
的调用,因为它无法知道这个函数没有副作用.
问题:有没有什么办法可以实现,让CFoo_getLength()
只有在程序中真正使用到长度时才会被调用? (而且对于 MyFoo
对象,它永远不会被调用多次?)有没有办法让编译器优化掉 CFoo_getLength()
调用(如果它足够聪明,可以推断出它是不需要)?
一种方法是在 class 中设置一个布尔标志,指示长度是否已被检索:
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()
内的额外计算。我想知道是否有编译时的解决方案。
您可以应用 pure
函数属性将 CFoo_getLength
标记为纯:
__attribute__ ((pure))
int CFoo_getLength(CFoo);
如您所见,令我对 C++ 没有经验的我感到惊讶的是,它允许 gcc 和 clang 优化您的原始代码。不错!
我正在构建一个 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()
而无需考虑性能。上述实现的缺点是它 总是 在创建每个 MyFoo
对象的过程中调用 CFoo_getLength()
,而不管它是否会在程序中实际使用.
即使 MyFoo
的所有成员函数都是内联的,我相信编译器不会优化掉对 CFoo_getLength()
的调用,因为它无法知道这个函数没有副作用.
问题:有没有什么办法可以实现,让CFoo_getLength()
只有在程序中真正使用到长度时才会被调用? (而且对于 MyFoo
对象,它永远不会被调用多次?)有没有办法让编译器优化掉 CFoo_getLength()
调用(如果它足够聪明,可以推断出它是不需要)?
一种方法是在 class 中设置一个布尔标志,指示长度是否已被检索:
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()
内的额外计算。我想知道是否有编译时的解决方案。
您可以应用 pure
函数属性将 CFoo_getLength
标记为纯:
__attribute__ ((pure))
int CFoo_getLength(CFoo);
如您所见,令我对 C++ 没有经验的我感到惊讶的是,它允许 gcc 和 clang 优化您的原始代码。不错!