2013-12-09 21 views
1

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

#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; 

} 

Assembler instructions此代码。分割错误到达20行(edx = 0)。

UPDATE。我会弄清楚有什么问题。为了稳定工作,需要声明k为双峰或添加到表达类operator =。与L常量&的情况是不正确的,因为它创建模板对象(Herb Sutter约const引用rvalue)。

+1

哪个编译器? g ++ 4.8.1编译这个罚款 –

回答

4

这是错误的:

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

L const& l; 

您结合l引用。然后,在您的使用情况:

Expression<Expression<doublet, plus, doublet>, plus, doublet> 
    k = b + a + c; 

b + a创建一个临时的,但它的存在只有等到语句结束。在下一行k.l是一个悬而未决的参考。

+0

是的 - 我会欢迎传递一个引用const引用是没有临时的! –

+0

是的,它的工作。然后在我的情况下,它不能工作。为什么我的案例与assert一起工作? – crastinus

+0

@crastinus:未定义的行为 –