边界检查const函数内的成员std :: array的问题

时间:2012-08-27 04:52:07

标签: c++ c++11 mingw

我正在使用以下代码检查带有mingw(gcc 4.7.0)的成员std :: array的奇怪行为边界

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

输出

0
1
0
2

该错误似乎与优化有关,因为它仅在使用-O编译时才会出现,我尝试了-O启用的单个标记,但无法进一步缩小范围。使函数非const也可以解决问题。这可能是一个错误,还是我错过了什么?

*修改

将其缩小,看起来像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';       
}

在Windows Xp sp3和Windows 7 sp1上使用mingw 4.7.0与-std=c++11 -O编译的输出相同。

*编辑2

再次输出

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

1 个答案:

答案 0 :(得分:5)

这是数组头

的一部分
#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(或将#ifdef更改为数组中的#ifndef)会导致输出正确。我不知道,这是正确的解决方案,但它确实有效。

UPD:我将数组标题中的代码更改为

#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

现在一切正常