2012-08-27 22 views
8

Me estoy poniendo límites comportamiento extraño de cheques un std :: miembro de matriz con MinGW (gcc 4.7.0) con el siguiente códigoProblema con la comprobación de límites un miembro std :: matriz dentro de una función const

#include <iostream> 
#include <array> 

class testClass 
{ 
    std::array<int, 2> testArray; 

    public: 
     testClass(); 
     void func() const; 

}; 

testClass::testClass() : testArray({{1, 2}}) 
{ 
} 

void testClass::func() const 
{ 
    for (int i = 0; i < 2; ++i) 
     std::cout << testArray.at(i) << '\n' << testArray[i] << '\n';  
} 


int main() 
{ 
    testClass test; 
    test.func(); 
} 

La salida es

0 
1 
0 
2 

El error parece estar relacionado con la optimización, ya que sólo surge cuando se compila con -O, probé las banderas individuales habilitados por -O pero no podía reducirlo más. Hacer que la función no const también solucione el problema. ¿Podría ser esto un error o me estoy perdiendo algo?

* Editar

restringido esta definición, se parece a un error en la versión de const.at()

#include <iostream> 
#include <array> 

int main() 
{ 
    std::array<int, 2> const testArray = {1, 2}; 

    for (int i = 0; i < 2; ++i) 
     std::cout << testArray.at(i) << '\n' << testArray[i] << '\n';  
} 

misma salida que el anterior compilado con -std=c++11 -O utilizando MinGW 4.7.0 en Windows XP SP3 y Windows 7 sp1.

* Editar 2

misma salida de nuevo

#include <iostream> 
#include <array> 

int main() 
{ 
    typedef std::array<int, 2> Tarray; 
    Tarray test = {1, 2}; 

    for (int i = 0; i < 2; ++i) 
     std::cout << const_cast<Tarray const*>(&test)->at(i) << '\n' << test.at(i) << '\n';  
} 
+0

http://liveworkspace.org/code/b0d5b3c7398f7e1a2e36838f23fc943c funciona bien. – ForEveR

+4

Definitivamente me parece un error. –

+0

Produce [una salida diferente] (http://ideone.com/ZhIsS) para mí ... – dasblinkenlight

Respuesta

5

Esto es parte de la cabecera gama

#ifdef __EXCEPTIONS 
    constexpr const_reference 
    at(size_type __n) const 
    { 
return __n < _Nm ? 
     _M_instance[__n] : throw out_of_range(__N("array::at")); 
    } 
#else 
    const_reference 
    at(size_type __n) const 
    { 
if (__n >= _Nm) 
    std::__throw_out_of_range(__N("array::at")); 
return _M_instance[__n]; 
    } 
#endif 

Undef __EXCEPTIONS en el archivo principal (o cambie #ifdef a #ifndef en serie) conduce a salida correcta No sé, esta es la solución correcta o no, pero funciona.

UPD: puedo cambiar el código en la cabecera de mi matriz a

#ifdef __EXCEPTIONS 
    constexpr const_reference 
    at(size_type __n) const 
    { 
return __n < _Nm ? 
     _M_instance[__n] : (throw out_of_range(__N("array::at"))), 
          _M_instance[__n]; 
    /*return __n < _Nm ? 
      _M_instance[__n] : throw out_of_range(__N("array::at"));*/ 
    } 
#else 
    const_reference 
    at(size_type __n) const 
    { 
if (__n >= _Nm) 
    std::__throw_out_of_range(__N("array::at")); 
return _M_instance[__n]; 
    } 
#endif 

Ahora todo está funcionando correctamente

+8

El error en el encabezado no enviado es ese '__n <_Nm? _M_instance [__ n]: throw out_of_range (__ N ("array :: at")) 'evalúa a prvalue temporary (porque un operador condicional debe evaluar a prvalue si uno de los operandos es una expresión' throw' - C++ 11 5.16/2). La vida útil de este temporal es solo hasta el final de la expresión completa de la declaración 'return' (C++ 11 12.2/5). Entonces la función 'at()' devuelve una referencia constante a algo que ya no es válido, el resultado es un comportamiento indefinido. –

+0

un error horrible ('return a? B: throw c;') --- no habría pensado que este tipo de error para principiantes viene con cualquier contenedor C++ enviado. – Walter

+3

@MichaelBurr: ¡Creo que puede valer la pena una respuesta propia! –

Cuestiones relacionadas