does new call class constructors?
Printable View
does new call class constructors?
Yes.Quote:
Originally Posted by Mitsukai
Regards,
Paul McKenzie
i have been having some trouble with my array class. when i called Size function. it gave me an memory error(critical send to microsoft crash error window thingie)
it pointed to the function Size at delete[] p_Array;
Code:template<typename _T>
class Array
{
protected:
_T* p_Array;
long p_Size;
public:
Array(long Size = 0)
{
if(Size < 0)
Size = 0;
p_Array = new _T[p_Size = Size];
}
~Array(void)
{
delete[] p_Array;
}
_T& operator[](long ID) const
{
if(ID < 0 || ID > p_Size)
ID = 0;
return(p_Array[ID]);
}
void Resize(long Size)
{
if(Size < 0)
Size = 0;
_T* Array = new _T[p_Size];
Array = p_Array;
delete[] p_Array;
p_Array = new _T[Size];
int X = 0;
while(X <= Size && X <= p_Size)
{
p_Array[X] = Array[X];
++X;
}
delete[] Array;
p_Size = Size;
}
long Size(void) const
{
return(p_Size);
}
void Size(long Size)
{
if(Size < 0)
Size = 0;
>>>>>>>>>>delete[] p_Array;
p_Array = new _T[p_Size = Size];
}
};
IsoMap(long Layers = 0, long Width = 0, long Height = 0)
{
p_Map.Size(Layers);
p_Pos.Size(Layers);
long L = 0;
long X;
while(L <= Layers)
{
p_Map[L].Size(Width);
p_Pos[L].Size(Width);
X = 0;
while(X <= Height)
{
p_Map[L][X].Size(Height);
p_Pos[L][X].Size(Height);
++X;
}
++L;
}
}
Hi Mitsukai,
Though the following is legal C++, it blows up in M$'s implementation (at least in the VC++ 6.0 era):
JeffCode:p_Array = new _T[p_Size = Size /*=0*/];
Also, an n element array is indexed 0 to n-1.
Code:_T& operator[](long ID) const
{
if(ID < 0 || ID > p_Size)
ID = 0;
return(p_Array[ID]);
}
i tried
makes no diffrenceCode:p_Array = new _T[Size]
well it would be better if you uased std::vector.
If you really can't and you have to write your own Array class (for a school exercise) then your best bet is to use a NULL pointer when the size is 0.
nothing is working... itried 1's isntead of 0's but it dint help. i will post more code...
Code:IsoMap<IsoTile> a;
//------------------------------------------------------------------------------------------------
struct IsoTile
{
long Obj;
long Set;
long X;
long Y;
};
//------------------------------------------------------------------------------------------------
template<typename _T>
class IsoMap
{
protected:
Array<Array<Array<_T> > > p_Map;
Array<Array<Array<RECT> > > p_Pos;
public:
IsoMap(long Layers = 0, long Width = 0, long Height = 0)
{
p_Map.Size(Layers);
p_Pos.Size(Layers);
long L = 0;
long X;
while(L <= Layers)
{
p_Map[L].Size(Width);
p_Pos[L].Size(Width);
X = 0;
while(X <= Height)
{
p_Map[L][X].Size(Height);
p_Pos[L][X].Size(Height);
++X;
}
++L;
}
}
CJArray& operator[](long ID) const
{
if(ID < 0 || ID > p_Map.Size())
return(NULL);
return(p_Map[ID]);
}
long Height(void) const
{
return(p_Map[0][0].Size());
}
long Layers(void) const
{
return(p_Map.Size())
}
long Width(void) const
{
return(p_Map[0].Size())
}
};
//------------------------------------------------------------------------------------------------
template<typename _T>
class Array
{
protected:
_T* p_Array;
long p_Size;
public:
Array(long Size = 0)
{
if(Size < 0)
Size = 0;
p_Array = new _T[Size];
p_Size = Size;
}
~Array(void)
{
delete[] p_Array;
}
_T& operator[](long ID) const
{
if(ID < 0 || ID > p_Size)
return((_T)NULL);
return(p_Array[ID]);
}
void Resize(long Size)
{
if(Size < 0)
return;
_T* Array = new _T[p_Size];
Array = p_Array;
delete[] p_Array;
p_Array = new _T[Size];
int X = 0;
while(X <= Size && X <= p_Size)
{
p_Array[X] = Array[X];
++X;
}
delete[] Array;
p_Size = Size;
}
long Size(void) const
{
return(p_Size);
}
void Size(long Size)
{
if(Size < 0)
return;
delete[] p_Array;
p_Array = new _T[Size];
p_Size = Size;
}
};
//------------------------------------------------------------------------------------------------
This sequence of steps is wrong. You should do the following:Code:_T* Array = new _T[p_Size];
Array = p_Array;
delete[] p_Array;
p_Array = new _T[Size];
- create a new array with the new size in a different variable
- copy everything over
- only then delete the old array
you are still calling new with a length of 0.
And don't overuse "Size" by making it both a member function and a local variable.
Hi,
Add an assert to snap the debugger:
Code:Array(long Size = 0)
{
if(Size < 0)
Size = 0;
ASSERT( Size > 0 );
p_Array = new _T[p_Size = Size];
}
im creating a copy of the old array so that i can preserve the old variables and im nto caling Resize anywhere so it shlnt be a rpoblem
error C2065: 'ASSERT' : undeclared identifierQuote:
that might be a problem. the size overloading...Quote:
Originally Posted by NMTop40
nope edited tto lSize, tested
itworked, so why woulndt mine work.Code:int* test = new int[0];
delete[] test;
nothing seems to be solving
No, that's not what your code does. Your code does the following:Quote:
Originally Posted by Mitsukai
Translated into words, this is:Code:_T* Array = new _T[p_Size];
Array = p_Array;
delete[] p_Array;
p_Array = new _T[Size];
int X = 0;
while(X <= Size && X <= p_Size)
{
p_Array[X] = Array[X];
++X;
}
delete[] Array;
1. Create a new array
2. Throw that array away by assigning the pointer to the old array (creating a memory leak)
3. Delete the existing array
4. Create a new array from scratch with the new size
5. Access invalid memory (memory that has been deleted already)
6. Delete the same array as in step 3, which you had already deleted.
Step 2 creates a memory leak. Step 5 is invalid and can lead to crashes, Step 6 will most likely crash.
Do you understand how pointers work in C++? A pointer is just a variable that holds the address to a memory location. Think of it as a piece of paper with the street and house number of a person's address. The data itself lives at the house. In step 1, you are building a new house and note that address down on a piece of paper called Array. In step 2, you take an eraser and erase the address on Array and write a new address on it, namely the address of the hous located at p_Array. So now, you don't know anymore where your newly built house is. This is the memory leak.
In this part of the code, there are three "houses" involved (i.e. three places in memory where data is stored as arrays):
1) The existing array, let's call it A (the "old" p_Array)
2) The one that you create in step 1. Call that B
3) The one you create in step 4, call that C.
So, with these names, let's go over the steps again.
1. Create array B and put its address in the variable Array
2. Array = p_Array, means that you don't know the address of B anymore, since now Array points to A.
3. Delete array A. At this point, you don't have any pointer to a valid array anymore, since A is destroyed, you lost track of B and C hasn't been created yet
4. Create C and put its address in p_Array
5. You try accessing A to copy elements from it to C. This is invalid because A has been destroyed
6. Delete array A again. It's also an invalid operation to delete the same array twice.
you have a poit there. i had not seen the pointer issue... But since i never call this function i dont see how it can create a problem in my situation.
would this work?btw i will give you post rating tomorow (24 limit :()Code:*Array = *p_Array;
Fix your array bounds in the calling functions. The issue is not Size() itself, but the fact that your are writing past the array bounds.
Arrays in C++ are [0 ... n-1] when created with new T[ n ];Code:p_Map.Size(Layers);
// ...
while(L <= Layers)
p_Map[L].Size(Width);
This is wrong in all your loops by the way. So loops should be like:
Code:for (L = 0; L < Layers; ++L)
You seem to be making string classes and array classes from all of your posts. Is this really what you were assigned from school? Was the assignment to make a dynamic array class, or are you really writing a larger application where you would like to use a dynamic array? If it is the latter, then you should stop wasting time making your own class and just use std::vector. That's what it's there for, so that you have a ready-made class and you can concentrate on other parts of your application.Quote:
Originally Posted by Mitsukai
I guess that "IsoMap" is what you're really trying to accomplish, and not really coding dynamic arrays. You have a buggy IsoMap because your dynamic array is buggy -- you have no idea if IsoMap works or not because the component that it relies on is faulty. This is why you should just use vector -- it works, and has no bugs. Then you can code your IsoMap with confidence that the underlying component is not at fault.Code:IsoMap(long Layers = 0, long Width = 0, long Height = 0)
Also, it seems you don't have a full grasp of the C++ language. Dynamic array classes are properly coded by persons who understand the C++ language, and really shouldn't be attempted by beginners. If you can't get pointers correct, then you won't be able to make progress without others practically writing the code for you. In any event, dynamic array classes are rarely even coded by professional programmers, since they have std::vector<> to do this.
In general, you are really missing out on learning C++ properly. That includes learning to use the standard library for things such as strings and dynamic arrays instead of creating your own.
But looking at your Array class, it contains no user-defined copy constructor and no assignment operator. You were told what the consequences are of leaving both of these out.
Regards,
Paul McKenzie
or i could fix it by doing new[n+1]...
yeah it worked.. thnx.. but now there the same error at closing...
i tested:
and it worked :DCode:int* TEST1 = new int[1];
int* TEST2 = new int[1];
TEST1[0] = 1;
TEST2[0] = 2;
*TEST1 = *TEST2;
MsgBox(TEST1[0]);
delete[] TEST1;
delete[] TEST2;
i dint see notice the pointer faults. they are fixed now. and i havent made the copy contructors yet becus i havent came around that yet and dint need it yet. this is my final assignment for school :) (a big one)
Yes it does work, but hopefully you see it is not necessary:Quote:
Originally Posted by Mitsukai
One word of advice: A C++ program that excessively uses "new" and "delete" does not make it an advanced program -- it makes it a poorly designed program.Code:int Test1 = 1;
int Test2 = 2;
Regards,
Paul McKenzie
so CString and vector doesnt use new?
you would be using std::string not CString.
As it happens std::vector does not use "new". It uses an allocator which is a template parameter. That allocator may use new or it may use malloc if it really wants. You don't need to worry about how it does it, just that it does.
It is a bit like if you are wiring up a house with electrical equipment. You will probably use standard components, rather than design your own switches.
Maybe, maybe not. The issue is if you use new or not, not whether the standard components use new.Quote:
Originally Posted by Mitsukai
Also it isn't your concern what is being used internally. All that you need to know is that these classes work. Also, for standard C++, the class is std::string, not CString.
I have a dynamic array of string, and added 4 strings to the array. This is a complete program. How many calls to "new" or "delete" do you see here? The answer is none, regardless of what vector or string do internally. Since this code does not make calls to new and delete, this moves the management of memory from the code that I wrote to the vector and string classes. Since the vector and string classes are correct, then this entire program works.Code:#include <string>
#include <vector>
int main()
{
std::vector<std::string> StringVector;
StringVector.push_back("This");
StringVector.push_back("is");
StringVector.push_back("a");
StringVector.push_back("test");
}
Here's the bottom line: If we were both to build the same application, I get more time to complete the more important parts of the program and I have built my program on a stable foundation since I used the standard classes. In your case, you're still trying to fixing bugs in your home-made array and string classes and basing the application on these buggy components. Now which is more productive, my approach or your approach?
If your coding your own array class to be used in a real program and you're using C++, then seriously, this type of work you're doing should be done only as an exercise, and should not be used in production code.
Regards,
Paul McKenzie
Whether they use new or not, does not matter.Quote:
Originally Posted by Mitsukai
These classes encapsulate their feature.
And they can replace new/delete.
And, with the principle : "never write the same thing twice", you should not use new/delete in two different classes where vector can be used.
Instead, you must use std::vector.
And if std::vector didn't existed, you would have written it, or found in on Internet, but only once in your life!
The only thing you need to know about std::vector is that if it is used on a UDT it will call that UDT's constructors.
Which ones will it call? Normally the default constructor and the copy constructor, so your class must have those defined.
If you initialise the vector with a parameter, it will call the constructor that takes that parameter and the copy constructor, and the one-parameter constructor may be explicit.
It also may call operator= on your class so you will need that defined.
It may call
which has a default behaviour of a default constructor and 3 assignments, but you can specialise that function to call a member-swap if your class has one (or implement the swap direct in that function, making it a friend if necessary). This should be done if your class has collections or other members that can be copied but would be more optimal to swap.Code:std::swap( YourClass &, YourClass & );