C++ 为什么我的超出范围异常没有被捕获
我是cpp的新手,我正在尝试一些东西。这件事我似乎无法独自解决C++ 为什么我的超出范围异常没有被捕获,c++,templates,error-handling,C++,Templates,Error Handling,我是cpp的新手,我正在尝试一些东西。这件事我似乎无法独自解决 #include <cstdio> #include <stdexcept> template <class E, class V> struct Pair { E first; V second; Pair(E fst, V snd) : first(fst), second(snd) {} E getFirst() { return first; }
#include <cstdio>
#include <stdexcept>
template <class E, class V>
struct Pair {
E first;
V second;
Pair(E fst, V snd) : first(fst), second(snd) {}
E getFirst() { return first; }
V getSecond() { return second; }
};
template <class t, unsigned dim>
struct vec {
t d[dim];
static constexpr int dimen = dim;
t &operator[](unsigned n) {
std::printf("dim: %d %d\n", dim, n);
if (n >= dim) {
std::printf("checking %d\n", n);
throw std::out_of_range("vector index is out of range");
}
return d[n];
};
};
int main() {
try {
Pair<int, vec<int, 2> *> test2(2, new vec<int, 2>{1, 2});
std::printf("%d\n", test2.getSecond()->dimen);
std::printf("before\n");
std::printf("%d\n", test2.getSecond()->d[2]); // it seems like the compiler kind of ignores this
} catch (std::out_of_range e) {
std::printf("Caught!!");
}
return 0;
}
现在,行std::printf%d\n,test2.getSecond->d[2];理想情况下,应该抛出超出范围的错误,但事实并非如此。我的皮棉实际上警告我,这也超出了范围。我可以编译并运行程序,它会返回一些垃圾0值
我的问题是:为什么没有抛出错误或者没有捕获错误?我认为没有抛出错误,因为在我运行它时没有打印检查。因为从未实际到达抛出代码
在此行中:
std::printf("%d\n", test2.getSecond()->d[2]);
getSection返回指向vec对象的指针。然后执行->d操作时,您正在访问vec对象中的d数组。因此,当您将[2]添加到末尾时,您正在访问数组索引2处的元素,而不是调用vec对象的运算符[]
如果您这样重写:
std::printf("%d\n", (*test2.getSecond())[2]);
然后将对vec对象而不是其数组调用运算符[]。请注意,必须取消对getSecond结果的引用。或者,您可以更加详细:
std::printf("%d\n", test2.getSecond()->operator[](2));
工作示例:,因为从未实际到达抛出代码
在此行中:
std::printf("%d\n", test2.getSecond()->d[2]);
getSection返回指向vec对象的指针。然后执行->d操作时,您正在访问vec对象中的d数组。因此,当您将[2]添加到末尾时,您正在访问数组索引2处的元素,而不是调用vec对象的运算符[]
如果您这样重写:
std::printf("%d\n", (*test2.getSecond())[2]);
然后将对vec对象而不是其数组调用运算符[]。请注意,必须取消对getSecond结果的引用。或者,您可以更加详细:
std::printf("%d\n", test2.getSecond()->operator[](2));
工作示例:非常好的问题
问题是,当您试图通过索引(如[2])引用数组中的项时,实际上是在引用size*2位置。没有针对它的内置保护,但您始终可以检查\0,因为这是阵列的终点。当您在C/C++中使用数组时,您的工作是确保您不在它们的位置之外。通常,最好将数组保存在结构/类中,并允许使用setter和getter访问其元素,这将处理边界并在违反边界时抛出异常。问得好
问题是,当您试图通过索引(如[2])引用数组中的项时,实际上是在引用size*2位置。没有针对它的内置保护,但您始终可以检查\0,因为这是阵列的终点。当您在C/C++中使用数组时,您的工作是确保您不在它们的位置之外。通常,最好将数组放在结构/类中,并允许使用setter和getter访问其元素,这将处理边界并在违反这些边界的情况下抛出异常。边界检查仅使用.at方法完成,而不使用索引运算符[]。->d[2]这将索引d成员,这是一个很好的旧C风格数组。这些方法的文档中对此进行了描述。请参阅并注意:通常,您应该通过常量引用捕获异常&在大多数情况下,不是通过值捕获异常。所以捕获常数std::超出范围&e。不会解决这个问题,只是一条关于最佳实践的建议。test2.getSecond->d[2]应该是*test2。getSecond[2]边界检查只使用.at方法完成,而不是使用索引运算符[]。->d[2]这将索引d成员,这是一个很好的旧C样式数组。这些方法的文档中描述了这一点。请参阅并注意:通常,您应该通过常量引用捕获异常&在大多数情况下,不是通过值捕获异常。所以捕获常数std::超出范围&e。不会解决这个问题,只是一条关于最佳实践的建议。test2.getSecond->d[2]应该是*test2.getSecond[2]