启用优化时 g++ 分段错误

cra*_*nus 3 c++ optimization segmentation-fault

当我启用优化(标志 -O2/-03)时,为什么此代码会生成分段错误。在返回之前添加断言,则一切正常。

#include <iostream>
#include <typeinfo>
#include <vector>
#include <assert.h>


struct doublet {

    doublet(double val1 = 0, double val2 = 0) {
        dob[0] = val1;
        dob[1] = val2;
    }

    template< class Expr >
    doublet& operator=(Expr const& x){
        dob[0] = x[0];
        dob[1] = x[1];
        return *this;
    }

    const double&  operator[](unsigned ix) const  {
      /*
       * BUG HERE
       */
      //assert(ix<2);
      return dob[ix];
    }


    void print(){
        std::cout << (*this)[0] << std::endl;
        std::cout << (*this)[1] << std::endl;
    }
private:
      double dob[2];
};

struct plus {

    static double  apply( double a,  double b)  {
        return a + b;
    }
};

struct minus {

      static double  apply(double a, double b){
        return a - b;
    }
};



template <class L, class OpTag, class R>
struct Expression {

    Expression (L const& l, R const& r) :l(l),r(r){}

    L const& l;
    R const& r;

    typedef const double result_type;

    result_type operator[](unsigned ix) const {
        return  OpTag::apply(l[ix],r[ix]);
    }

};

template <class L, class R>
Expression<L,plus,R> operator+(L const& l, R const& r){
    return Expression<L,plus,R>(l,r);
}

template <class L, class R>
Expression<L,minus,R> operator-(L const& l, R const& r){
    return Expression<L,minus,R>(l,r);
}

int main()
{
    doublet a(4.0,1.0), b(5.1,3.3), c(7.4,5.2);

    Expression<Expression<doublet, plus, doublet>, plus, doublet> 
    k = b + a + c;
    std::cout << k[0] << " " << k[1] << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

这段代码的汇编指令。在第 20 行 (edx=0) 上达到分段错误。

更新。我会弄清楚是什么问题。为了稳定工作需要将 k 声明为doublet或添加到表达式类operator=。带有L const& 的情况是不正确的,因为它创建了模板对象(关于对右值的 const 引用的Herb Sutter)。

zch*_*zch 5

这是错误的:

Expression (L const& l, R const& r) :l(l),r(r){}

L const& l;
Run Code Online (Sandbox Code Playgroud)

l通过引用具有约束力。然后在您的使用中:

Expression<Expression<doublet, plus, doublet>, plus, doublet> 
    k = b + a + c;
Run Code Online (Sandbox Code Playgroud)

b + a创建一个临时的,但它只存在到语句结束。下一行k.l是一个悬空引用。