2013-12-09 5 views
1

Почему этот код генерирует ошибку сегментации, когда я включаю оптимизацию (флаг -O2/-03). Когда добавьте assert перед возвратом, тогда все ОК.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).

ОБНОВЛЕНИЕ. Я выясню, в чем проблема. Для стабильной работы необходимо указать k как дублет или добавить в класс выражения operator =. Случай с L const & не прав, поскольку он создает объекты шаблона (Herb Sutter о константе ссылки на 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

Yep - Я бы приветствовал передачу ссылок на const, где эта ссылка не временная! –

+0

Да, это работает. Тогда в моем случае это не должно работать. Почему мое дело работает с утверждением? – crastinus

+0

@crastinus: неопределенное поведение –

Смежные вопросы