为什么编译器不能优化它?

时间:2017-07-02 11:57:20

标签: c++ gcc clang

看看这段代码:

struct Data {
};

struct Init {
    Data *m_data;

    Init() : m_data(new Data) { }
    ~Init() {
        delete m_data;
    }
};

class Object {
    private:
        const int m_initType;
        Data *m_data;
    public:
        Object(const Init &init) : m_initType(0), m_data(init.m_data) { }
        Object(Init &&init) : m_initType(1), m_data(init.m_data) { init.m_data = nullptr; }
        ~Object() {
            if (m_initType==1) {
                delete m_data;
            }
        }
};

void somefunction(const Object &object); // it is intentionally not defined

void callInitA() {
        Init x;
        somefunction(x);
}

void callInitB() {
        somefunction(Init());
}

由于Object::m_initType是const,它在构造函数之后不会改变。因此,理论上,在callInitAcallInitB中,编译器在内联m_initType时知道~Object()的值。但是,gcc和clang fails to apply都是这种优化,并且都会检查m_initType的值。

为什么?是否有针对此优化的语言规则,或者编译器不进行此类优化?

(这个问题与this密切相关,但这是一个更具体的问题,我希望我能得到答案)

2 个答案:

答案 0 :(得分:3)

要回答是否有禁止此类优化的语言规则,请参阅此处

来自[dcl.type.cv]

  

除了可以修改声明为mutable的任何类成员之外,任何在其生命周期内修改const对象的尝试都会导致未定义的行为。

理论上,优化器可以安全地假设m_initType在初始化后永远不会改变。这当然可以用来推断~Object中的分支是否会在编译时被采用。

也就是说,只要观察到的行为保持不变,优化者就可以自由地做任何事情,他们也可以自由地忽略const。为了使优化器更复杂,在混合中有一个前向声明但未定义的函数,优化器可能在此之后就放弃了对信息做任何有用的事情。

Comparison of defined vs undefined function

如果稍后定义该函数,gcc和clang都会优化一切。但请注意,在这种特殊情况下,即使没有任何const,它们也会still do this

可能会感兴趣

This post

答案 1 :(得分:0)

在您的示例中没有内联对象析构函数,并且您有2个调用,其中一个m_initType是1而另一个是0.因此编译器必须支持这两个版本。 此外,我认为您的实际代码比您的示例稍微复杂一些,因此编译器可能会认为内联整个析构函数代码比使用单个“if”内部的通用版本更昂贵。