在您的代码中,您正在为myvect[ans] 之类的向量编制索引,但索引为ans 的元素可能不存在,即myvect.size() <= ans,C++ 默认情况下不进行边界检查。因此,您有超出范围的段错误。
C++ 旨在超级高效和快速。因此,在标准库的每个地方,如果程序员没有明确要求,C++ 不会进行检查。
只有像 Python 或 JavaScript 这样的可编写脚本的语言会一直到处检查,但这有时会使它们比 C++ 慢 100-200 倍。
在std::vector 中有一个索引的边界检查变体,您必须使用myvect.at(and),它与myvect[ans] 相同,但如果索引超出范围则会引发异常。但不要忘记使用try-catch 语法捕获异常。
但.at() 方法仍然不会自动调整数组大小以添加新元素。为了获得自动调整大小的功能,您必须自己在您的矢量类版本中实现该功能。
接下来我编写了我的自动调整大小版本。默认情况下,它还对[] 运算符进行异常检查。您可以使用任何自定义行为从标准 C++ 库中扩展任何类,就像我在下面为 std::vector 所做的那样。
下一个代码的输出:
Trying VectorT == "Vector<Vector<int, std::allocator<int> >, std::allocator<Vector<int, std::allocator<int> > > >"
use_at == true
1 2 3
Trying VectorT == "Vector<Vector<int, std::allocator<int> >, std::allocator<Vector<int, std::allocator<int> > > >"
use_at == false
1 2 3
Trying VectorT == "std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >"
use_at == true
Exception: vector::_M_range_check: __n (which is 2) >= this->size() (which is 0)
Trying VectorT == "std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >"
use_at == false
exited, segmentation fault
Try it online!
#include <vector>
#include <iostream>
#include <string>
#ifndef _MSC_VER
// Only for Unix demangling
#include <cxxabi.h>
#endif
using namespace std;
template < typename T, typename AllocatorT = typename std::vector<T>::allocator_type >
class Vector : public std::vector<T, AllocatorT> {
private:
typedef std::vector<T, AllocatorT> SuperT;
inline void FitSize(size_t i) {
if (i > SuperT::size())
SuperT::resize(i);
}
public:
template <typename ... Args>
Vector(Args ... args) : SuperT(args ...) {}
inline T & operator[] (size_t i) {
FitSize(i + 1);
return SuperT::operator[](i);
}
inline T const & operator[] (size_t i) const { return SuperT::at(i); }
inline T & at(size_t i) {
FitSize(i + 1);
return SuperT::at(i);
}
inline T const & at(size_t i) const { return SuperT::at(i); }
};
// This function is just for informational purposes of demangling
char const * Demangle(char const * name) {
#ifdef _MSC_VER
return name;
#else
int status = 0;
return abi::__cxa_demangle(name, 0, 0, &status);
#endif
}
template <template < typename T, typename AllocatorT = typename std::vector<T>::allocator_type > class VectorT>
void Test(bool use_at) {
try {
VectorT< VectorT<int> > myvect;
cout << "Trying VectorT == \"" << Demangle(typeid(myvect).name()) << "\"\n use_at == " << (use_at ? "true" : "false") << endl;
int ans = 2, n = 3;
for(int i = 0; i < n; i++)
{
if (!use_at)
myvect[ans].push_back(i+1);
else
myvect.at(ans).push_back(i+1);
ans++;
}
for(int i = 0; i < myvect.size(); i++)
{
if(!myvect[i].empty())
{
for(auto x: myvect[i])
cout << x << " ";
}
}
cout << endl;
} catch (exception const & ex) {
cerr << "Exception: " << ex.what() << endl;
} catch (...) {
cerr << "Unknown Exception!" << endl;
}
}
int main() {
Test<Vector>(true);
Test<Vector>(false);
Test<vector>(true);
Test<vector>(false);
return 0;
}