2012-08-27 18 views
8

Dostaję dziwne zachowanie granic sprawdzanie std członek :: tablicę z MinGW (GCC 4.7.0) z następującym kodemProblem z mechanizmu sprawdzania członka std :: tablicę const wewnątrz funkcji

#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(); 
} 

wyjście jest

0 
1 
0 
2 

błąd wydaje się być związane z optymalizacją, gdyż uprawy tylko gdy skompilowany z -O starałem poszczególne flagi włączone przez -O ale nie mógł sprowadzić dalej. Utworzenie funkcji non-const również rozwiązuje problem. Czy to może być błąd, czy też coś mi brakuje?

* edit

zmniejszyła go, wygląda na błąd w wersji .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';  
} 

samo wyjście const jak wyżej skompilowany z -std=c++11 -O użyciu MinGW 4.7.0 na Windows XP SP3 i Windows 7 sp1.

* edit 2

samo wyjście ponownie

#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 działa dobrze. – ForEveR

+4

To zdecydowanie wygląda jak błąd. –

+0

Generuje [inną wydajność] (http://ideone.com/ZhIsS) dla mnie ... – dasblinkenlight

Odpowiedz

5

Jest to część nagłówka tablicy

#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 w głównym pliku (lub zmienić #ifdef do #ifndef w tablicy) prowadzi do prawidłowe wyjście. Nie wiem, to jest właściwe rozwiązanie, ale działa.

UPD: zmienić kod w nagłówku mojego tablicę do

#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 

Teraz wszystko działa poprawnie

+8

Błąd w niezałagowanym nagłówku jest taki, że '__n <_Nm? _M_instance [__ n]: throw out_of_range (__ N ("array :: at")) zwraca wartość tymczasową (ponieważ operator warunkowy musi oszacować wartość prinalu, jeśli jednym z argumentów jest wyrażenie 'throw' - C++ 11 5.16/2). Czas życia tymczasowego jest tylko do końca pełnego wyrażenia instrukcji "return" (C++ 11 12.2/5). Tak więc funkcja 'at()' zwraca odwołanie do wartości stałej, która nie jest już prawidłowa - wynikiem jest niezdefiniowane zachowanie. –

+0

straszny błąd ('return a? B: throw c;') --- nie pomyślałby, że ten rodzaj błędu początkującego przychodzi z jakimkolwiek dostarczonym kontenerem C++. – Walter

+3

@MichaelBurr: Myślę, że może być warta własnej odpowiedzi! –

Powiązane problemy