【发布时间】:2016-11-22 03:02:15
【问题描述】:
我正在尝试为 std::vector 创建一个容器类,以自学更多关于模板、重载运算符和管理异常的知识。
目前,我只是定义基本操作。我有一个下面列出的模板类;我已经用T 将+= 和[] 运算符重载为push_back 和vector,并分别直接访问向量的元素。这按预期工作。
+= 操作符做了它应该做的事情,并且尝试对超出范围的元素使用[] 操作符将按预期抛出异常。
这是原型类和当前的实现:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <class T>
class Inventory
{
public:
void operator += (const T& b) { backpack.push_back(b); }
T operator [] (const unsigned& b)
{
if (backpack.empty() || backpack.size() < b)
throw string("Out of Range");
return backpack[b];
}
void operator -= (const unsigned& b)
{
if (backpack.empty() || backpack.size() < b)
throw string("No such element exists.");
backpack.erase(backpack.begin() + b);
}
private:
vector<int> backpack;
};
int main()
{
Inventory<int> pack;
pack += 2;
pack += 4;
try
{
cout << "It was " << pack[0] << endl;
cout << "It was " << pack[1] << endl;
pack -= 0;
cout << "It is now " << pack[0] << endl;
//pack -= 1; // Segfaults?
}
catch (string e)
{
cout << "Error: " << e << endl;
}
}
问题在于-= 运算符,旨在擦除右侧指示位置的元素。当我停留在向量的边界内时,这会按预期工作;但是,如果我指定要擦除的越界数字,我不会得到异常;我得到了一个 seg-fault 。我试图通过添加额外的打印命令来确定段错误发生的确切点:
void operator -= (const unsigned& b)
{
cout << "In Overload!\n";
if (backpack.empty() || backpack.size() < b)
{
cout << "Exception!\n";
throw string("No such element exists.");
}
backpack.erase(backpack.begin() + b);
}
“例外!”线永远达不到。即使我应该评估未定义的行为,程序也会在它达到那个点之前出现故障。我相信我错过了理解这个过程如何工作的关键组成部分。有没有办法我应该写这个所以它可以抛出而不是错误?
在 Linux x64 架构上使用 g++ -std=c++17 -Wall -Wextra -pedantic 编译。
【问题讨论】:
-
为什么不简单地使用
std::vector::at()而不是为无效索引编写自己的测试?vector::at()保证会抛出out_of_range异常。 -
““异常!”cout 永远不会到达。程序在到达该点之前发生故障“ - 你怎么知道程序将到达那个点?也许它去叫
backpack.erase。 -
@PaulMcKenzie 也许这是一个编码练习。
-
确实如此。正如我所提到的,我正在自学 C++。因此,当我去学习一个新概念时,我倾向于尝试将新事物分解成块。首先,我专门为整数编写了这段代码。然后我把它变成了一个模板。然后我添加了错误处理和异常抛出。接下来我将使用标准异常,添加特性方法等等。我发现这让我更容易掌握新信息而不会不知所措。不过谢谢你的回复。我很感激!
-
一些注意事项:索引到容器中的正确数据类型是
size_t,而不是unsigned int(尽管在某些实现中它们可能相同)。除非这是为了学习,否则您可能不应该遇到这个异常。修复程序状态没有任何意义。它遇到了意外情况,唯一安全的选择是让它终止。默认情况下,当您遇到未捕获的异常时会发生这种情况。
标签: c++ vector exception-handling segmentation-fault