This question already has answers here:
Object array initialization without default constructor
(14 answers)
Closed 3 years ago.
So, I have an object with a constructor. This object doesn't support empty constructors because there are constants that must be assigned in the constructor. Something like this:
class Object {
public:
const int foo;
Object(int f) : foo(f) {
// other stuff
}
}
Now I have another function that keeps a dynamically allocated array of objects.
Object* objects;
I need to be able to allocate this memory using new[] and delete[] but also use the constructor. I can't seem to figure out how to do this.
Something like this would be ideal
objects = new Object[numObjects];
for (int i = 0; i < numObjects; ++i) {
object[i](foos[i]);
}
I could use malloc and free, then new the objects in place, but that would be non ideal as I would have to loop through the objects in the destructor and manually destruct them, then free the memory. Seems messy.
You could use list initialisation:
objects = new Object[3]{1, 2, 3};
But this only works with a constant size array.
I could use malloc and free, then new the objects in place
This is indeed exactly the way to create an array of dynamic length containing objects of a non-default-constructible type. Except instead of malloc, it would be more idiomatic to allocate an array of std::byte with new[]. This is also how to allocate an array of certain number of objects that you would like to create later.
But there's no need to write that yourself, since the standard library provides you with std::vector, which does this for you:
std::vector<Object> mycars(numObjects, Object(42));
Related
This question already has answers here:
C++ Correct way to free a vector of a custom class
(3 answers)
Closed 5 years ago.
I've been working on an implementation of the n-bodies problem, and I have to make a struct (asteroid) and a vector which contains those structs.
My question is, if I create the vector like this:
vector<asteroid> b(n_asteroids + n_planets);
And then I fill it like this:
for (it = 0; it < n_asteroids + n_planets; ++it){
b[it] = {arg1, arg2, arg3...}
}
Do I need to call delete for either the asteroid structs or the vector? Or will the destructor free them when my program ends main?
Thanks!
You don't need to delete your vector, as you didn't use new to allocate it. Regarding vector members, from http://www.cplusplus.com/reference/vector/vector/~vector/
This calls allocator_traits::destroy on each of the contained elements, and deallocates all the storage capacity allocated by the vector using its allocator.
So the answer is no for you case.
But note that if you hold pointers in your vector, e.g. vector<asteroid *>, which you allocated with new, and you don't have any reference left to this pointer, you will need to manually delete it.
Your vector has an automatic storage class which means the memory it occupies will be released when it will go out of scope. This means that the contents of the vector will be released too.
If the vector held pointers that pointed to dynamically then you would have the need in delete.
I am learning c++ and I have these doubts:
I want to initialize the array at run time but the size of array also needs to be read at run time.
int size;
int main(){
//read size
size = <value read above>;
CIwUIButton* buttons[size];
}
This does not compile and says size must be constant.I come from Java background and I could achieve the same functionality by following same logic.How to do it in c++.
I am using vector as an equivalent to Java ArrayList.I want a reference to vector outside main but want to initialize it inside main.Again max_size will be read from user input and all elements should be initialized to 0;
vector<int> elements;
int main(){
//read size
int size = <value read above>;
//how to do following in c++
elements = new vector<int>(size);
}
Right, so C++ is not Java, and Java is not C++. They are both separate languages.
If you have an unknown number of "things", you need to use either a vector or dynamically allocate using new. So if you want size number of CIwUIButton pointers:
CIwUIButton** buttons = new CIwUIButton*[size];
(Make sure you use delete [] buttons later - after deleting each button).
If you want size number of buttons:
CIwUIButton* buttons = new CIwUIButton[size];
Again, use same as above to delete the buttons, but you won't need to delete the buttons themselves)
You could also use vector for CIwUIButton.
If you want size number of integers in a global vector called elements then:
elements.resize(size);
(There is near no situation where you need to call new for a vector object - that's probably wrong, unless you know exactly why you are doing it)
For the first part;
you need to allocate array dynamically as follows:
CIwUIButton** buttons = new CIwUIButton*[size];
(Do not forget to delete that object and its elements using destructor and delete [].)
If you want to use non-default constructor you need to initialize each object in a loop:
for(int i=0;i<size;i++) {
buttons[i] = new CIwUIButton(x,y);
}
Second question;
std::vector<int> elements;
You do not need to give a size, however you can define a size like this:
elements.resize(size);
In C++, we follow this idiom known as RAII.
Resource Acquisition Is Initialization.
When you declare an instance of an object A inside a scope:
{
A instance;
}
This object will be destroyed when we leave the scope.
In the case of your global std::vector<int>, it will be created and initialized when the program begins execution and it will be deallocated when the program terminates.
There is no need for new and delete in such a case.
std::vector has a resize method that allows you to resize the internal array so you can access and modify the elements via operator[]. You can also push_back or emplace_back without having to resize.
You can use vector just like this:
vector<int> elements;
int main(){
//read size
int size = <value read above>;
//how to do following in c++
elements.resize(size, 0);
}
In Java, all new objects need to be created with the "new" keyword, but in C++ that is not always the case. elements will be a constructed object by virtue of its declaration, ready to use in main. You can set its size by calling the resize method. Alternatively you can declare elements in main (and not outside as a global variable) and pass the size of the vector as a constructor arguement.
These are basic topics and I suggest you read tutorials on C++ before continuing.
You can make buttons a
vector<CIwUIButton *>
and set its size in the class constructor. But you will also need to manage how the button elements are created.
Variable length arrays are introduced in C99, but C++ doesn't support it.
To use vector:
vector<int> elements;
int main(){
//read size
int size = <value read above>;
elements.resize(size);
}
std::vector doesn't have a fixed size there is no reason to initialize to a specific size, it will just grow on demand. You can do elements.reserve(size) which allocates space for the size elements (ints in your example).
t and all elements should be initialized to 0;
Your elements vector is not a pointer its an Object that is constructed by calling the constructor there is no dynamic memory management needed as it is not even allocated on the heap.
new and delete (don't forget deletes , or better use smart pointers) are used with pointers only.
example :
int main()
{
std::vector<int> elements; // not a pointer constructor called because of this statement
std::vector<int> *elements_ptr = new std::vector<int>(); // this is a pointer pointers have asterisks as part of their declaration and these are initialized via new they simply contain a memory location
// do stuff here
delete elements_ptr; // frees allocated memory and calls the destructor for the object
return 0;
} // elements destructor is called when it goes out of scope
If you are this new to the language I highly recommend reading a book about C++.These are things that are best described by such material.
I would recommend deitel's how to program C++ or the C++ programming language by Bjarne Stroustrup
For using new you'll just need a vector<int>* pointer. The preferred solution for C++ is to use the vector<T>::resize() operation:
vector<int> elements;
int main(){
//read size
int size = <value read above>;
//how to do following in c++
elements.resize(size,0);
}
First I wouldn't use global variables, it is some kind of evil.
If you do not know, how many objects/variables you will need, you have two options, either use some container, or dynamically allocate memory.
I would suggest to use container, but first about dynamical allocation. In C malloc and free in C++ new and delete. C type allocation gives you piece of memory and C++ type does the same and calls constructor and destructor, I suggest to use C++ allocators.
How to use it:
Object *ptr; //pointer to some object
ptr = new Object; //creating one object
delete ptr; //deleting that object, destructor called and memory deallocated
ptr = new Object[n]; //created n objects, to reach any of them just use array index
delete [] ptr; //deleted array. n destructors called all memory freed
If you create array of object, do not use delete without [].
So it is about your own allocators. In your case using vector is probably the best option. But I'll say it once again, global variables is bad idea. I would recommend to pass a reference to it when you call function.
There are a few ways of function prototypes in C++
/*1*/foo(Object obj); //value of given object will be copied it's slow but sometimes we need that
/*2*/foo(Object *obj); //passing pointer more C type. Fast but unsafe.
/*3*/foo(Object &obj); //C++ passing reference. It is the same as passing pointer but it is C++ type declaration, it is safer because you won't pass NULL and you won't go out of memory
/*4*/foo(const Object *obj);
/*5*/foo(const Object &obj); //Same as before one is C type, another C++ type (unsafe and safer). Keyword `const` means what value won't be changed.
Calls to these functions look like this:
Object obj;
/*1*/foo(obj);
/*2*/foo(&obj);
/*3*/foo(obj);
/*4*/foo(&obj);
/*5*/foo(obj);
So going back to your question.
If you really want to use global variable, so you will need to resize your container. In your case it is elements.resize(size); But I wouldn't use global data so my option would be:
typedef std::vector<CIwUIButton> ButtonVector; //in big projects typedef makes us to type less :)
size_t size = <value read above>;
ButtonVector buttons(size); //You will need default constructor to initialize all buttons
I've seen a pointer in your code, not sure, what you wanted to do with that but I think it is not necessary.
BTW you should read about STL containers because C++ and JAVA differs. Especially read about vector and deque. In your case vector is probably better then deque but you mentioned ArrayList and it is much more deque then vector.
EDIT If you are really want to start programming with C++ you should also look at boost in your case scoped_array and shared_ptr may be useful.
You have to allocate memory dynamically, use malloc and assign sizeof(yourClass) * size to the pointer you have created
I am dynamically allocating memory for an array in a function. My question is: once the function finishes running is the memory freed?
code:
void f(){
cv::Mat* arr = new cv::Mat[1];
...
}
No, memory allocated using new is not automatically freed when the pointer goes out of scope.
However, you can (and should) use C++11's unique_ptr, which handles freeing the memory when it goes out of scope:
void f(){
std::unique_ptr<cv::Mat[]> arr(new cv::Mat[1]);
...
}
C++11 also provides shared_ptr for pointers you might want to copy. Modern C++ should strive to use these "smart pointers", as they provide safer memory management with almost no performance hit.
No, it is not. You must free it by calling
delete[] arr;
But you should ask yourself whether it is necessary to allocate dynamically. This would require no explicit memory management:
void f(){
cv::Mat arr[1];
...
}
If you need a dynamically sized array, you could use an std::vector. The vector will internally allocate dynamically, but will take care of de-allocating it's resources:
void f(){
std::vector<cv::Mat> arr(n); // contains n cv::Mat objects
...
}
No. Every call to new needs to be matched up with a call to delete somewhere.
In your case arr iteself is a variable with automatic storage duration. This means that arr itself will be destroyed when it goes out of scope. However the thing that arr points to does not, because that is a variable that does not have autoatic storage duration.
The fact that arr itself has automatic storage duration can be used to your advantage, by wrapping the raw pointer in a class that destroys the stored pointer when the automatic object is destroyed. This object utilizes an idion known as RAII to implement a so-called "smart pointer". Since this is a very common requirement in well-designed applications, the C++ Standard Library provides a number of smart pointer classes which you can use. In C++03, you can use
std::auto_ptr
In C++11 auto_ptr has been deprecated and replaced by several other better smart pointers. Among them:
std::unique_ptr
std::shared_ptr
In general, it is a good idea to use smart pointers instead of raw ("dumb") pointers as you do here.
If what you ultimately need are dynamically-sized arrays, as supported by C99, you should know that C++ does not have direct support for them. Some compilers (notably GCC) do provide support for dynamically sized arrays, but these are compiler-specific language extensions. In order to have something that approximates a dynamically sized array while using only portable, Standards-compliant code, why not use a std::vector?
Edit: Assigning to an array:
In your comments you describe the way in which you assign to this array, which I have taken to mean something like this:
int* arr = new int[5];
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
If this is the case, you can accomplish the same using vector by calling vector::operator[]. Doing this looks uses very similar syntax to what you've used above. The one real "gotcha" is that since vectors are dyanamically sized, you need to make sure the vector has at least N elements before trying to assign the element at position N-1. This can be accomplished in a number of ways.
You can create the vector with N items from the get-go, in which case each will be value-initialized:
vector<int> arr(5); // creates a vector with 5 elements, all initialized to zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
You can resize the vector after the fact:
vector<int> arr; // creates an empty vector
arr.resize(5); // ensures the vector has exactly 5 elements
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
Or you can use a variety of algorithms to fill the vector with elements. One such example is fill_n:
vector<int> arr; // creates empty vector
fill_n(back_inserter(arr), 5, 0); // fills the vector with 5 elements, each one has a value of zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
No, of course not.
For every new you need precisely one delete.
For every new[] you need precisely one delete[].
Since you don't have the matching delete[], your program is broken.
(For that reason, the adult way of using C++ is not to use new or pointers at all. Then you don't have those problems.)
No. The array the allocated on the heap, you'll have to delete it before it goes out of scope:
void f() {
cv::Mat * arr = new cv::Mat[1];
// ...
delete [] arr;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How does delete[] know it's an array? (C++)
How does delete[] “know” the size of the operand array?
suppose we have the following class
class Data
{
public:
Data() : i(new int) { *i = 0; }
~Data() { delete i; }
private:
int *i;
};
now we create array of 100 elements of type Data
Data* dataArray = new Data[100];
we know that operator new will call Data constructor for the 100 objects because it knows how many objects created, Now let's delete this array, if we say delete dataArray the destructor for first object only will be called even we know that the memory for the 100 objects we be released - will cause memory leak - and that because they allocated as one block, but if we say delete[] dataArray the destructor for the 100 objects will be called, but this is a dynmaic memory and i didn't specify how many object in there and as i know there is no overhead with the array to know how many objects in it, so how the runtime environment knows the number of objects to destruct before it free that memory?
First, delete dataArray is illegal. It might destroy the first object. It might do nothing. It might crash. It might summon demons through your nose. Don't do it.
As for how delete [] determines how many elements to store, it depends on the C++ library implementation. Typically there's an element count right before the first element (this may be part of the metadata that's always associated with dynamic allocations, or it might be extra data added for delete []); the delete [] implementation will look at this count to determine how many times to call the destructor; it will then adjust the pointer to point before the element count before actually freeing the memory (this is one reason why delete dataArray can break badly).
It depends on what the compiler does, but basically 2 options :
Store data just before the actual objects (array size, allocated size), a la malloc.
Keep a global map of pointers associated with an array size.
That's why you need to use either operator delete or the operator delete[] in each particular case. They are not interchangeable and they do different things. The implementation keeps some compiler/library-specific bookkeeping information about each memory block that these operators use.
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").