I thought I did something stupid - at least I thought it was. My question is: why does this work?
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;
}
The code works perfectly in C++14 (Visual Studio). Shouldn't it throw an exception after the second push_back?
Update question:
What if you don't initialize pContainer with new, but with pContainer = &T() instead? Doesn't that affect somehow the memory or even endanger other programs? When I use a class that prints out when it was constructed/destructed, all objects that were created will be destroyed right after the construction. Why can I use them even after destruction?
delete[] pContaineris also undefined behaviour - it should bedelete[] (T *)pContainer;operator delete[]takevoid*anyway, so there would be no point of casting your pointer to an actual type pointer, since it would degrade back intovoid*anyway.T*, so must delete aT*. This code deletes avoid*. The compiler doesn't just calloperator delete(). It calls destructors for theTobject(s) that were allocated. Deleting avoid*at best doesn't run any destructors; worse, it might corrupt memory. For scalar types that often doesn't matter, but it's still wrong.