我以为我做了些蠢事 - 至少我以为是这样。我的问题是:为什么这有效?
template<typename T>
class yarray
{
public:
yarray() {
pContainer = new T[1]; //initialize as array with size 1
unCount = 0U; //counter
}
~yarray() {
delete[] pContainer; //cleanup
pContainer = nullptr;
}
void push_back(T data)
{
((T*)pContainer)[unCount] = data; //set (shouldn't it throw an exception when unCount > 0?
unCount++; //increment
}
T operator[](const unsigned int & index)
{
if (index <= unCount)
return ((T*)pContainer)[index];
return T();
}
private:
void * pContainer;
unsigned int unCount;
};
int main()
{
yarray<int> klo;
klo.push_back(342);
klo.push_back(5563);
for (auto i = 0; i < 2; ++i)
std::cout << klo[i] << std::endl;
}
该代码在C ++ 14(Visual Studio)中完美运行。它不应该在第二个push_back
之后抛出异常吗?
更新问题:
如果您不使用新内容初始化pContainer
,但使用pContainer = &T()
初始化该怎么办?不会以某种方式影响记忆甚至危及其他程序吗?当我使用在构造/破坏时打印出来的类时,所有创建的对象将在构造后立即销毁。为什么即使在破坏后我也可以使用它们?
答案 0 :(得分:7)
具有越界数组访问权限的程序具有未定义的行为。不需要抛出异常。
至于它为何起作用,这只是运气不好。
答案 1 :(得分:1)
计算机的可寻址存储器设置为多个页面。目前的作物有4k(4096字节)。在现代操作系统上,4k内存可以寻址,也可以不寻址。
要使程序失败,那么内存需要
只有在这些情况属实时,系统才会出现故障。
诸如valgrind(linux)和应用程序验证程序(windows)之类的程序会修改内存分配系统以设计这种形式的故障,但是如果没有这个系统,那么代码就不会总是出错。
在更简单的系统(例如arduino)上,所有内存都可用,这绝不会出错。会发生什么,是内存属于其他东西,并导致难以找到错误。