C++ 在常量函数中检查成员std::数组时出现边界问题
我用以下代码检查mingw(gcc4.7.0)的成员std::array时发现了奇怪的行为边界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
#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