c++ - 使用 2D 向量时出现分段错误
问题描述
我可以确切地知道为什么我的代码在开始遍历或将输入输入 2D 向量时出现分段错误吗?我不明白是什么导致了问题。
编辑:这myvect[ans].push_back
是造成问题的部分。
所以我的问题是为什么它不只是向后推并在 myvect[ans] 位置创建一个向量?这不是动态向量应该做的吗?这是我的代码:
vector<vector<int>> myvect;
int ans = 2;
for(int i = 0; i < n; i++)
{
myvect[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<<" ";
}
}
解决方案
在您的代码中,您正在索引向量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
#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;
}
推荐阅读
- c# - hive jdbc 驱动程序:javax.xml.stream.XMLStreamException:尝试输出第二个根,
- load-balancing - 如何在 HAProxy 中使用 external-check 命令
- clojure - 使用 map 时收集顺序颠倒,但使用 mapv 很好
- php - Laravel 5.4:返回响应 json groupBy created_at
- node.js - npm npm run watch-poll 宅基地错误
- glsl - 计算着色器和工作组
- amazon-web-services - 如何使用 lambda 和 SQS 实现优先级队列架构?
- excel-formula - 有没有办法从连接结果中删除空换行符?
- spring - Websphere - Spring 集成 SSL 问题
- python - 没有烧瓶 sqlalchemy 或 ORM 的烧瓶登录