有没有办法让编译器优化对外部函数的多次调用?

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 优化您的原始代码。不错!