I wonder whether memory for array member of a class be allocated in c++.
In my class, I defined array member like this:
class A
{
public:
B* B_array[1000];
}
and, in the constructor, I want to use it:
A::A()
{
for(int i = 0; i < 1000; i++)
{
B_array[i] = new B;//can i use B_array[0...999]???
}
}
B* B_array[1000];
What you have is an array of 1000 pointers to the type B.
for(int i = 0; i < 1000; i++)
{
B_array[i] = new B;//can i use B_array[0...999]???
}
Allocates memory to each pointer in the array, after this statement each pointer points to a memory on heap.
So yes you can use each of them, once this code is executed.
Yes, you can. When you enter the body of constructor, there are 1000 uninitialized pointers waiting for you to initialize them.
What you should do, though, is use std::vector<B>
class A
{
public:
std::vector<B> array;
}
A::A() : array(1000) {}
and be done with it. Vector allocates its elements dynamically.
Yes you can. Memory for 1000 pointers will be allocated always. However those pointers will not be initialised unless you do that yourself (as you are in your contructor code).
I wonder whether memory for array member of a class be allocated in c++
Yes, why not. If your doubt is about allocating an array the way you are doing, it is possible. If your doubt is about calling B's constructor while still being in A's constructor, then also there is absolutely no issues with that.
In general, however there are several things that I would take care in the code shown e.g. not hard coding the value 1000, checking for exception from new etc.. you get the idea.
And you should also be bothered about releasing the memory resource in the destructor of A explicitly.
Yes, the memory for 1000 pointers of B class instances will be allocated. You have defined an array B_array[1000] of B* objects. It's the same as int integerArray [1000]. You just store pointers in the array, not values.
However you will need to initialize them to point to the actual objects on the heap.
Related
#include <iostream>
class A {
public:
A(int d) : y(d) {}
int y;
};
int main(void) {
A d[3] = {A(0), A(1), A(2)};
std::cout << d[1].y << std::endl;
};
I'm working on a project for university. I'm instructed not to use an object array and instantiate each element with a temporary object of my class - so something like the above code is a no-no. Instead, it's recommended we use a an array of type A* and then use new on each element so that we create an object and make each element point to it.
So we'd have something like this:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
However, I don't quite understand the difference in practice when compared to the first version. As far as I understand in the first version we we create the three temporary objects (which are rvalues) using the constructor and then assign them to the array. After the assignment ends, the temporary is destroyed and its values are copied to the array. In the second version, we have the advantage of being able to delete what d[] points to but disregarding that, what is the drawback of using the first method?
EDIT:
class B{
public:
A a1[3];
}
Assuming my initial definition is followed by this (A isn't default constructible, is something like this impossible? So in that case I can't an array of objects and I instead have to resort to a pointer array of type A* and then use new, as my only resort.
Array of pointers -> memory allocation when you create an object and assign it to the pointer. Array of 1000 pointers with 1 element inside = 1x the memory.
Array of objects -> memory allocation when you create an array. Array of 1000 with 1 element inside = 1000x the memory.
1 ) A d[3], it creates a built-in array (or C-style, plain, naked array...) which contains (three) elements of type A, these elements live on the stack (according to your code).
2 ) A* d[3];, it creates a built-in array which contains (three) pointers to elements of type A (or they should). It doesn't mean that the pointed element is of type A, it's developer's task to create those elements, and you can do it in two ways, using the stack (as before):
A element;
...
d[0] = &element;
or using the heap (with new/new[] and delete/delete[]):
d[0] = new A;
...
delete d[0];
Side effects of the second option; you may point to an already destroyed element (i.e. the element is out of scope), hence potential seg fault; you may loose the pointer to the allocated memory (i.e. the array of pointers is out of scope and the allocated memory has not been released), hence memory leak.
However, an advantage is that you can use lazy initialisation (you don't pay for what you don't use). If you don't need an A object in d[2] (or pointed by), why should you create it and waste memory? And here smart pointers arise, they make your life easier allowing you to allocate memory only when you need it, reducing the risk of seg faults (worth it to mention std::weak_ptr), memory leaks, etc:
std::unique_ptr<A> d[3];
d[0] = std::make_unique<A>(); // Call make_unique when you need it
But still a bit nasty, the built-in arrays are good but may be much better under some circumstances. It is hard to add or remove elements, iterate, get the size, access to the tail/head, etc... And that's why containers are quite useful, i.e. std::array or std::vector (where its size doesn't have to be known at compilation time):
std::vector<std::unique_ptr< A> > d(3);
std::array<std::unique_ptr<A,3> > d;
There are no advantages whatsoever to the following code in C++:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
In fact, you shouldn't write it at all.
Your solution with a locally-declared temporary array is valid, but has the significant limitation of requiring that the number of elements in the array be a compile-time constant (i.e., known ahead of time).
If you need to have an array with a dynamic number of elements, known only at run time, then you should use a std::vector, which performs the new allocation automatically. That is the idiomatic way of working with dynamically-allocated arrays in C++.
I'm constructing a struct with one of the member being a map.
First question is this allowed? The compiler did not complain.
struct A {
map<int, float> B;
}
Later I declare an array of such data type.
A *C = (A *)INTERNAL_CALLOC(..., sizeof(A));
Here the function INTERNAL_CALLOC is a functional wrapper of MALLOC.
Later on in the code when I try to first time insert an item into the array's first element's map, I got a core dump.
C[0].B[0] = 0.001;
Any idea why is this the case?
Thanks!
Yes, a map in a struct is fine.
Allocating with malloc is definitely not fine; the constructor is not called. So your map will most likely do something terrible when you attempt to use it.
General rule of thumb: don't use malloc/calloc/realloc/free in C++. Avoid dynamic allocation wherever possible, and use new/delete when unavoidable.*
* And read up on smart pointers.
If you really must allocate with INTERNAL_CALLOC, then use placement new.
First, you must define a constructor and a destructor for the type A, or define A as a class:
struct A {
A(){}
~A(){}
map<int, float> B;
};
Then you can simply call:
//Allocate an A, uninitialized
A *C = (A *)INTERNAL_CALLOC(..., sizeof(A));
//Initialize the newly allocated A
new (C) A();
later when you free the object you must explicitly call the destructor:
//A *C;
C->~A();
INTERNAL_free(C);
A *C = (A *)INTERNAL_CALLOC(..., sizeof(A));
Here you are lying to the compiler. You are telling it that the return value from INTERNAL_CALLOC points to an A, but it doesn't, it just points to zeroes. Use new.
You don't get a valid std::map<whatever...> by filling memory with zero bytes.
To a certain extent, it's possible with POD types (approximately, "pure C" data structures).
Since you use std::map as a member,
I recommend to use std::vector instead of plain array to be the container.
You can do as follow:
struct A
{
std::map<int, int> B;
};
std::vector<A> vecofmap;
A elem0;
A elem1;
A elem2;
vecofmap.push_back(elem0);
vecofmap.push_back(elem1);
vecofmap.push_back(elem2);
vecofmap[0].B[0] = 100;
std::cout << vecofmap[0].B[0] <<std::endl;
Then no needs to bother with memory allocation.
Allocating memory using malloc does not initialize the array elements.
For example i have class with constructor that has array of ints as parameter:
A(int* array) : m_array(array) {}
I can use it like this:
int array[] = { ... }
A a(array);
Or like this:
int* array = new int[10];
A a(array);
If object then use it array, it must (or may be not?) delete it in desctructor (if it was dynamic). But how he will know, that memory for this array was allocated dynamically?
You can't know if it's dynamically allocated or not, because after all, int* array is an int pointer, not an array. You might as well pass:
int i;
A a(&i);
As you can imagine, bad things will happen if you try to delete[] that one, or try to access m_array[N] with N > 0.
So you have to rely on the caller to do the right thing; there's nothing you can do to verify or enforce it. All you have is the address of an int. Who created that int, or how or whether more ints follow after it, will be unknown.
If you want more safety, use an std::vector. This is what it was made for.
You're initializing the array in the constructor, so it will always be initialized. It is pre-defined in the code that it will be allocated. If there are other constructors that do not allocate your array, you will need to do this check.
By the way, this is under the assumption that the array you are allocating is a member of the class. If you are assigning it to a new stack variable within the constructor, you won't be able to delete it in the destructor.
From what i understand you are trying to ask is whether the destructor will free the memory you have allocated to the array.
No, the memory you have allocated using new will have to be deleted by you either in the destructor or somewhere else the pointer is in scope as your memory allocation is not inside the constructor but outside.
You cannot know what it was because a static array decays into a pointer as well.
Basically you just need the value of the array passed to the constructor. You need not know whether it was a dynamically allocated or statically allocated array. What matters is the data member array which is part of the interface of your class and into which you are copying the data. Responsibility of the array passed to the constructor as an argument should rest with the caller regarding its deletion and lifetime.
It would make your life easier if you use std::vector instead of raw array.
Suppose I have an array of objects of type Foo in C++:
Foo array[10];
In Java, I can set an object in this array to null simply by:
array[0] = null //the first one
How can I do this in C++?
Use pointers instead:
Foo *array[10];
// Dynamically allocate the memory for the element in `array[0]`
array[0] = new Foo();
array[1] = new Foo();
...
// Make sure you free the memory before setting
// the array element to point to null
delete array[1];
delete array[0];
// Set the pointer in `array[0]` to point to nullptr
array[1] = nullptr;
array[0] = nullptr;
// Note the above frees the memory allocated for the first element then
// sets its pointer to nullptr. You'll have to do this for the rest of the array
// if you want to set the entire array to nullptr.
Note that you need to consider memory management in C++ because unlike Java, it does not have a Garbage Collector that will automatically clean up memory for you when you set a reference to nullptr. Also, nullptr is the modern and proper C++ way to do it, as rather than always is a pointer type rather than just zero.
So, forget Java here, it's not helping you. Ask yourself; what does it mean for an object to be null? Can an object be null? The answer is no, an object can not be null, but a reference (pointer in C++ terms) to one can be.
In java you have reference types, which are similar to pointers under the hood. However, you cannot set objects to null even in java, only references.
In C++ you have fully fledged objects and pointers and references to objects. A pointer to an object (or primitive type) can be null, but an object itself cannot.
So, when you create an array of Foo objects you have, well, an array of Foo objects. You don't have pointers, you have objects. If your array were an array of pointers to objects then yes, you could initialize them to null (nullptr in C++0x), i.e., they don't refer to a valid object.
Other way that you have is using one dynamic array of pointers of Foo like this:
Foo** array = new Foo*[10];// Pointer of array of pointers.
Then you can initialize all this pointers to objects Foo
for(int i=0;i<10;i++)
array[i] = new Foo();// Give memory to pointers of object Foo in array
assign null to one item of array:
array[0] = 0;
I think that in C++, NULL is 0. This means it can even be assigned to an int or anywhere a 0 is acceptable. Conventionally, it's only used with pointers.
For delete this memory:
for(int i=0;i<10;i++)
delete array[i];
and finally
delete[] array;
Code Example:
#include <iostream.h>
#include <stdio.h>
class Foo
{
private:
int a;
public:
Foo()
{
a = 0;
}
void Set_V(int p){a = p;}
int Get_V(){return a;}
};
int main()
{
Foo **array = new Foo*[10];
for(int i=0;i<10;i++)
{
array[i] = new Foo();
}
//array[0] = 0;
for(int i=0;i<10;i++)
array[i]->Set_V(i);
for(int i=0;i<10;i++)
cout<<array[i]->Get_V()<<endl;
for(int i=0;i<10;i++)
delete array[i];
delete[] array;
return 0;
}
so is there away to "remove" an element in the array without creating a new one? i.e making a hole in the array of some sort?
In C++, if you have an array:
Foo array[10];
Then all 10 elements will be default-constructed. In general, there's no concept of array elements being in use vs. "removed". One way to track this idea is to make having actual values in the array elements optional, as in:
boost::optional<Foo> array[10];
You can read about the boost library's optional<> library at http://www.boost.org/doc/libs/release/libs/optional/
For the sake of documenting alternatives, I'll cover a hideous one. You could call the destructor on one of the elements: array[3].~Foo(); This is very dangerous as when the array itself goes out of scope, the destructor for each element will be called, and a precondition for that is to have a properly constructed object, so you have to be sure to have constructed a Foo in that element again beforehand (using "placement" new). There is nothing in the array itself that will help you keep track of which elements have had their destructors called by you - you'd need to track that yourself (having some record of this inside the objects would probably work in practice, but accessing the object after destruction is undefined behaviour). You'd need to be very careful that in all code paths - including those due to exceptions - you tracked the momentarily unused array elements. You really don't want to do this.
If your concern is to remove an element from the array to save memory, then use smart pointers:
shared_ptr<Foo> array[10];
You can then control specific array elements independently, with only still-populated elements being destructed when the element goes out of scope. Suitable smart pointers are available in boost or C++11, or you could use std::auto_ptr<> but should carefully read about its semantics beforehand to see if it's suitable and how to safely use it.
Separately, if there's a Foo::operator=(Some_Type*) then you could set array[3] = NULL;, and it would do whatever that assignment operator did to array[3]. Still, if Foo is not a pointer, it is probably a bad idea for it to allow someone to assign NULL to it.
I'm a bit confused about handling an array of objects in C++, as I can't seem to find information about how they are passed around (reference or value) and how they are stored in an array.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space. I try to create a dynamic array of myClass objects within a myContainer. In the myContainer.addObject() method I attempt to make a bigger array, copy all the objects into it along with a new object, then delete the old one. I'm not at all confident that I'm cleaning up my memory properly with my destructors - what improvements could I make in this area?
class myClass
{
private:
string myName;
unsigned short myAmount;
public:
myClass(string name, unsigned short amount)
{
myName = name;
myAmount = amount;
}
//Do I need a destructor here? I don't think so because I don't do any
// dynamic memory allocation within this class
};
class myContainer
{
int numObjects;
myClass * myObjects;
public:
myContainer()
{
numObjects = 0;
}
~myContainer()
{
//Is this sufficient?
//Or do I need to iterate through myObjects and delete each
// individually?
delete [] myObjects;
}
void addObject(string name, unsigned short amount)
{
myClass newObject = new myClass(name, amount);
myClass * tempObjects;
tempObjects = new myClass[numObjects+1];
for (int i=0; i<numObjects; i++)
tempObjects[i] = myObjects[i]);
tempObjects[numObjects] = newObject;
numObjects++;
delete newObject;
//Will this delete all my objects? I think it won't.
//I'm just trying to delete the old array, and have the new array hold
// all the objects plus the new object.
delete [] myObjects;
myObjects = tempObjects;
}
};
An array in C++ is an array of objects laid out in memory.
So for example in:
struct pair {
int x; int y;
};
...
pair array[10];
Each item in the array is going to be with a size of two ints.
If you want an array of pointers you can simply declare one:
pair* array_of_pointers[10];
The string objects have pointers to the variable size part of the string. So they're safe.
In fact they're the important lesson here. Same way you use the string class to avoid excessive memory handling you can use the vector class to avoid all the troubles of handling a dynamic array.
For the case you're doing this as an exercise. Here are a few problems:
newObject needs to be allocated locally, without new. This will make the code correct (as newObject is not a pointer and new returns a pointer) and will also save you the trouble of explicitly handling memory. (On a more advanced note, this makes the code exception safe in one more location)
myObject is never initialized. And you don't use initialization lists in the constructor. The constructor should look like this:
myContainer() : numObjects(0), myObjects(NULL)
{
}
The destructors in the code are exactly as they should be.
No, a dynamic array is not an array of pointers to that type - its a pointer to the first element. The elements are laid out consecutively in memory and are destroyed when the array is delete[]ed.
Thus your deallocation looks fine - you create dynamic arrays of myClass objects so you don't have to delete them individually. You would only have to do this if you had an array of pointers to (dynamically allocated) objects.
There are two definitive errors though:
tempObjects[numObjects] = newObject; // assign a myClass pointer to a myClass instance?
This should be e.g.:
tempObjects[numObjects] = myClass(name, amount);
Also, myObjects is never initialized, which means it contains garbage and dereferencing/using it leads to undefined behaviour.
Finally, unless you are doing this for learning purposes, simply use containers like std::vector that do all the work for you already.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
The array will consist of the objects themselves. If you want to have an array of pointer you will have to declare that:
myClass ** tempObjects;
tempObjects = new myClass*[numObjects+1];
I assume you are used to C# or Java? In those languages objects can only be allocated on heap and are always accessed by referenced. It is possible in C++, but in C++ you can also put objects directly on the stack, or directly construct an array of the objects themselves.
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space?
Number two: The string object itself is constant in size, but has a pointer to a dynamically sized buffer allocated from the heap.
I think the deallocation looks fine. The code could be written more efficient in various ways, but it looks correct.
Try to test it, to see what happens (yes, that may be compiler-specific, but still)...
You could try to add a custom destructor to myClass (even though you don't need one), that increments a "global" counter when called, Then print the counter after deleting the array.
I would expect the destructor of each object to be called. Note that quite often objects are stored "by-pointers" to allow for inherited objects to be put into the array (avoiding "slicing").