C++ 在常量函数中检查成员std::数组时出现边界问题

C++ 在常量函数中检查成员std::数组时出现边界问题,c++,c++11,mingw,C++,C++11,Mingw,我用以下代码检查mingw(gcc4.7.0)的成员std::array时发现了奇怪的行为边界 #include <iostream> #include <array> class testClass { std::array<int, 2> testArray; public: testClass(); void func() const; }; testClass::testClass() : tes

我用以下代码检查mingw(gcc4.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();
}
这个错误似乎与优化有关,因为它只在使用
-O
编译时出现,我尝试了
-O
启用的各个标志,但无法进一步缩小范围。使函数为非常量也解决了这个问题。这可能是一个bug还是我遗漏了什么

*编辑

缩小范围,看起来像
const
版本的
.at()


这是数组头的一部分

#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

现在一切都正常了

运行得很好。对我来说,它确实像个bug。它为我生成了…g++4.8.0(实验版),所有代码都只在-O0下运行良好。对于其他-O标志给出了这样的警告:“在这个函数中未初始化使用[-Wuninitialized]”我无法在ubuntu linux上用gcc 4.7或4.8快照重现该警告。未修补头中的错误是
\n<\n Nm_M_实例[u n]:抛出范围之外的值(u n(“数组::at”)
计算为临时prvalue(因为如果其中一个操作数是
抛出
表达式-C++11 5.16/2,则条件运算符必须计算为prvalue)。此临时变量的生存期仅在
return
语句(C++11 12.2/5)的完整表达式结束之前。因此,<代码>())/>代码>函数返回一个不再有效的const引用——结果是未定义的行为。一个可怕的bug(<代码>返回a;b:抛出c;< /COD>)---不会想到这种初学者错误会随任何被装运的C++容器来。“MichaelBurr:我认为这可能是一个值得自己回答的问题!”沃尔特,你为什么认为这是初学者的错误?
(返回a?b:throw c;)
本身没有什么问题,如果函数没有通过引用返回就可以了。这样写是为了让
array::at
成为
constexpr
(但正如Michael指出的,它不起作用。)
#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';       
}
#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';     
}
#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
#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