C++ C++;具有相同if语句的内联方法

C++ C++;具有相同if语句的内联方法,c++,compiler-optimization,inline-method,C++,Compiler Optimization,Inline Method,我正在为OpenGL纹理编写处理程序,我正在考虑安全性和性能。哪一级的优化应该删除标记的if语句 struct Texture2D { GLuint ID; inline Texture2D(): ID(0) {}; inline explicit Texture2D(GLuint id): ID(id) {}; ~Texture2D(); void GenTexture(bool regen = false); void DeleteTex

我正在为OpenGL纹理编写处理程序,我正在考虑安全性和性能。哪一级的优化应该删除标记的if语句


struct Texture2D {
    GLuint ID;

    inline Texture2D(): ID(0) {};
    inline explicit Texture2D(GLuint id): ID(id) {};
    ~Texture2D();

    void GenTexture(bool regen = false);
    void DeleteTexture();

    void BindTexture();

    void Parameterf( GLenum pname, GLfloat param );
    void Parameteri( GLenum pname, GLint param );
    void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params );
    void glTexParameteriv( GLenum target, GLenum pname, const GLint *params );

    static Texture2D binded;
};
inline void Texture2D::GenTexture(bool regen) {
    if(ID){
        if(regen)
            DeleteTexture();
        else
            return;
    }

    glGenTextures(1,&ID);
}

inline void Texture2D::DeleteTexture() {
    glDeleteTextures(1,&ID);
    ID = 0;
}

inline void Texture2D::BindTexture() {
    glBindTexture(GL_TEXTURE_2D, ID);
    binded.ID = ID;
}

inline void Texture2D::Parameterf( GLenum pname, GLfloat param ){
    if(binded.ID == ID)                          // THIS
        BindTexture();                           // THIS

    glTexParameterf(GL_TEXTURE_2D,pname,param);
}

inline void Texture2D::Parameteri( GLenum pname, GLint param ){
    if(binded.ID == ID)                          // THIS
        BindTexture();                           // THIS

    glTexParameterf(GL_TEXTURE_2D,pname,param);
}

inline Texture2D::~Texture2D() {
    DeleteTexture();
}

// in this function
void loadTexture(...) {
    Texture2D t;
    t.GenTexture();
    t.BindTexture();
    // if statements in next functions
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
}

这取决于编译器,您最好的选择是测试-编译并检查发出的机器代码。

任何优化级别都无法(正确)删除这些测试。只有当两个参数都是编译时常量,而这两个参数都不是,或者编译器可以证明它们不会在测试之间更改值时,才能删除它们

由于绑定的
是静态的,编译器无法知道对GL函数的调用不会改变它。

无。

悲伤故事,但C++假定如果调用函数,则此函数可能产生各种副作用,包括更改BIDED.ID的值(函数不知何故要做)

如果您确保您调用的函数绝对没有合法的方式来了解您的
bindend.ID
,可以直接(通过引用它)或间接(因为其他人拿着它的指针并传递它)。下面是一个简单的示例(假设
副作用()
位于不同的翻译单元中)

side_effect()
可以合法地使用和更改
k
,方法是将其声明为外部。不能优化掉
副作用的调用

int side_effect();
static int k=1; 

int main()
{
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}
副作用
无法以允许的方式访问
k
,因为您无法访问其他翻译单元中的静态数据。因此,代码可以优化为
副作用();返回0
,因为只要内存中没有出现副作用(),k就不会改变。这当然是未定义的行为

int side_effect();
void snitch(int*);

static int k=1; 

int main()
{
    snitch(&k); // !!!
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}
编译器无法知道
snitch()
是否将其参数保存在
side\u effect()
可以更改它的位置,因此无法消除对
side\u effect()
的调用

如果将
k
作为局部变量,则会出现相同的情况:如果某个未知例程可能以合法方式访问
k
,则编译器无法基于k的值进行优化


PS:生成
k
const没有帮助,因为丢弃const是合法的。常量不能用作优化提示。

为什么任何级别的优化都应该这样做?这些不是
吗=?(还有,bind的过去分词是bind)您是否打算将这些测试设置为
=?编译器将很难证明在opengl调用期间静态变量没有被修改,因此一般来说,它无法消除条件测试。@Neil;它们是内联的,所以只需要第一个。@行我不知道内联与它有什么关系。不完全正确,如果它们是stackframe的本地对象,也可以删除它,但它们是全局的+不管怎样,它都不应该依赖于编译器,因为正如路德·布利塞特所解释的那样。变量可以在GL调用期间更改。实际上,最好的方法是只编写清晰的代码,并且只有在确定这些语句是瓶颈时才进行优化。但是,测试是确定编译器功能的唯一方法。进行链接时代码生成的现代编译器可能有信息知道k是否会因副作用而改变。然而,在C++中证明它是安全的还是非常困难的,所以我不期望它,并且同意实践中的答案。
int side_effect();
void snitch(int*);

static int k=1; 

int main()
{
    snitch(&k); // !!!
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}