我正在尝试制作自己的向量,但遇到以下问题:当我push_back 100次时,没有问题。当我push_back 1000时,程序无法运行
#include <iostream>
#include <stdlib.h>
#include <conio.h>
struct Exception {
static const char* out_of_range;
};
const char* Exception::out_of_range = "[Error]: Out of range";
template < typename T >
struct vector {
typedef T myType;
public:
vector() {
m_vector = (myType*) malloc ( sizeof( myType ) );
m_position = 0;
}
template < typename ... Ts >
vector(myType head, Ts ... tail) {
m_position = 0;
m_vector = (myType*) malloc( (sizeof ...( tail ) + 1) * sizeof( myType ) );
this->push_back(head);
(this->push_back(tail),...);
}
~vector() {
free(m_vector);
m_vector = NULL;
}
void push_back( myType value ) {
m_vector[ m_position ] = value;
++m_position;
m_vector = (myType*) realloc(m_vector, m_position * sizeof(myType));
}
void pop_back() {
--m_position;
m_vector = (myType*)realloc( m_vector, m_position * sizeof (myType) );
}
myType at( size_t pos ) {
try {
if (pos < m_position)
return m_vector[ pos ];
else throw Exception::out_of_range;
} catch (const char* e) {
printf("%s", e);
return (myType){};
}
}
inline myType& front() { return *m_vector; }
inline myType& back() { return *(m_vector + size() -1); }
inline myType* data() { return m_vector; }
inline myType* begin() { return m_vector; }
inline myType* end() { return (m_vector + size()); }
inline myType operator[](size_t pos) { return m_vector[ pos ]; }
inline size_t size() { return m_position; }
inline bool empty () { return (begin() == end()? true:false); }
private:
myType* m_vector;
size_t m_position;
};
这是我主要使用push_back的100次:
int main() {
vector<int> v;
for(int i = 0; i < 100; ++i) v.push_back(i);
for(int i = 0; i < 100; ++i) std::cout << v[i];
}
下面是被搜寻的代码:
int main() {
vector<int> v;
for(int i = 0; i < 1000; ++i) v.push_back(i);
for(int i = 0; i < 1000; ++i) std::cout << v[i];
}
对于“不起作用”,我想说的是,当我通过push_back插入100个值时,程序会向我显示0到99之间的所有值...但是当我有1000个值时(我不会(不知道为什么),该程序仅显示黑屏,仅此而已
答案 0 :(得分:4)
考虑
的首次通话void push_back(myType value) {
m_vector[m_position] = value; // Store into 0
++m_position; // set `m_position` to 1
m_vector = (myType*)realloc(m_vector, m_position * sizeof(myType)); // Allocate more space.
}
最后一行分配了多少空间? m_position * sizeof(myType)
。解析为1 * sizeof(myType)
。 1 myType
的空间足够。换句话说,程序已经具有相同的空间量。这没有用。
让我们看看下一个push_back
void push_back(myType value) {
m_vector[m_position] = value; // Store into 1. There is no 1. Program now broken
++m_position; // set `m_position` to 2
m_vector = (myType*)realloc(m_vector, m_position * sizeof(myType)); // Allocate more space.
}
下一个push_back
写入无效的存储。程序现已正式破坏,无需进一步调试。
我们如何解决这个问题?
让我们忽略一个事实,即malloc
以及家庭don't handle complex data structures和vector
没有遵守the Rules of Three and Five。最好在其他问题中解决这些问题。我们如何用realloc
来解决这个问题?
m_vector = (myType*) realloc(m_vector, (m_position +1) * sizeof(myType));
使当前的粗糙区域变得平滑。但这效率低下。每次添加都会触发重新分配。这确实确实损害了性能。聚合O(1)随即被O(n)所取代,每次复制,再加上可能非常昂贵的内存分配。 1
更糟糕的是,删除项目时会发生什么?您无法掌握向量中的多少,并且可能会发现自己realloc
正在使用较小的缓冲区。好吧。
要正确执行此操作,首先添加一个m_capacity
成员以跟踪可以存储多少数据,这样,如果所需数量少于所需数量,我们就不必重新分配。
然后我们测试空间量,并可能在尝试存储之前重新分配。
void push_back( myType value ) {
if (m_position >= m_capacity)
{ // need to reallocate
m_capacity *= 2;
myType * temp = (myType*) realloc(m_vector, m_capacity *sizeof(myType));
// ask for more than is needed. Reduce number of reallocations needed
// do not overwrite m_vector. realloc can fail to allocate and then where are you?
if (temp != NULL)
{
m_vector = temp;
}
else
{
// handle error. Probably throw exception. Definitely exit function
// before trying to add new element
}
}
m_vector[ m_position ] = value; // now guarantied to have space.
++m_position;
}
1 严格来说,这不是真的。您会发现的一件事是,所提供的内存通常不如您所要求的那样精细。当程序要求X字节时,它可能会获得一个方便的空闲内存块,该块大于X字节。您曾经注意到,有时您可以在缓冲区末尾运行,而程序没有注意到并立即崩溃?多余的空间是原因之一。 realloc
经常可以利用这一优势,并一遍又一遍地使用相同的分配,从而使程序可以合法地查看更多信息。但是,您不能指望这一点。
答案 1 :(得分:2)
我假设您的代码背后的想法是m_vector应该总是比现在拥有更多的值。那么您的push_back函数是错误的,应该为m_position + 1重新分配。