How should class fields be declared in C++? - c++

I need to declare and initialize a vector as a field of a class named PixelOperator.
I am torn between these two declaration methods, the first is "on the heap", and the second "on the stack" (or at least, that is my interpretation).
vector<int>* field = new vector<int>();
vector<int> field = vector<int>();
If I choose to declare in style number 1, I need to call delete in the destructor of the class.
Which one should I choose, and why?
Also, if the class is initialized on the heap (ie. PixelOperator* op = new PixelOperator();), are fields initialized on the stack initialized on the heap?

Choose method 2. That would put the object on the stack, but the vector's implementation will most likely put the contents on the heap.
Also, you have the meanings reversed. 1 is on the heap, 2 is on the stack. 1 will require delete.

Your intuition is wrong in this instance. Approach (2) does not necessarily put the vector on stack. If PixelOperator object is declared locally and thus put on stack, the vector is put on stack as well, but if the PixelOperator object is put on heap using new operator, the vector also gets put on heap as part of that object. The difference in this instance would be that in approach (2) the vector is part of a contiguous block of memory together with other object fields, and in approach (1), the block of memory containing the object has in it address of another block of memory, which contains the vector. Of course, in approach (1) the vector ends up on heap regardless of whether the PixelOperator object is put on heap or on stack. Approach (2) is generally more desirable, as it allows for more transparency determining where the object gets allocated.

There is nothing to stumble on. There is never a reason to allocate std::vector<> (or any other standard container for that matter) on a heap. Simply never do this and you will be alright.

Related

Adding an element that is declared on the stack to a static array

Let's say I have a std::vector which is declared as static. Can I add objects, which are declared locally on the stack of a calling function to the vector without repercussions?
From my understanding, the vector stores its elements on the heap. Meaning if I tell the vector to MOVE the element like this
myvector.push_back(std::move(element));
it will be stored on the heap and its visibility will be preserved, right?
Edit: I would want to avoid the object from being copied because it manages other resources.
Am I correct? Or can this be done easier?
You generally can copy initialise objects with dynamic storage by copying from objects with automatic or static storage and vice versa. Whether the object is copied by moving does not matter.
There can in theory be classes that only work correctly when allocated in certain way, but such classes should be made non-copiable to prevent problems.

In C++, is created vector or map in a function on stack or heap?

I just have a very simple question but I can not find it through google.
In C++, if we create a integer in a function, I believe it will be in stack. But if we create a vector or a map, for example,
vector<int> a
will it on stack or heap? I believe that's kind of class object(similar to the object created by "new" in java) so probably it should be on heap?
The vector<int> object itself is created in the storage of your choice: if you declare it as a local variable, that would be in the automatic storage.
However, the vector is usually represented as a pair of pointers; the data for that vector is allocated in the dynamic storage area.
Same goes for std::map<K,V>: the object goes wherever you put it (automatic, static, or dynamic memory, based on your declaration) while the data goes into the dynamic storage area.
Starting with C++11 you can use std::array<T> class for fixed-size collections. The data of this collection will go entirely in the storage where you put the collection itself. However, such collections are not resizable.
The data for any dynamically sized object like that will be heap allocated. If it were on the stack it would risk an overflow and a program crash if it grew too large.
The object itself (i.e. the size of the dynamic array and the pointer to the data's location in memory) will likely be stored on the stack.
Yes this will also be created on the stack.
Variables are only created on the heap when new or malloc is called.
The type doesnt really matter, what matters is how its created.
If you're trying to decide whether or not to create a varaible on the stack or dynamically (on the heap), you should consider the lifetime of the object. If you just need it during the scope that its created in, then create it on the stack. Otherwise create it dynamically.
Here, the vector is stored both on the heap and on the stack. Meaning, the header is on the stack, but as you put elements into the vector, those are dynamically allocated, hence on the heap.

fully deallocating the memory of a std::vector container

From the vector docs it would appear that the proper way to completely deallocate a vector of values to which you have a class member pointer such as:
std::vector<MyObject>* mvMyObjectVector_ptr;
...
//In the class constructor:
mvMyObjectVector_ptr = new std::vector<MyObject>();
would be to invoke the following, in order, in the class's destructor implementation
mvMyObjectVector_ptr->clear();
delete mvMyObjectVector_ptr;
However, this appears to be leading to SIGABRT 'pointer being freed was not allocated' errors. Is the above idiom the correct way to completely deallocate the memory held at the address pointed to by a pointer to a vector (if it is, I assume my errors are coming from something else)? If not, what is the correct way?
Yes, it is correct, provided mvMyObjectVector_ptr has been allocated using new.
Additionally, MyObject needs to satisfy certain requirements before it can be used with std::vector.
The call to clear() is redundant and can be omitted.
Some likely reasons for the SIGABRT include:
mvMyObjectVector_ptr hasn't been allocated using new;
MyObject violates the Rule of Three;
the class the contains the vector violates the Rule of Three.
I don' think your problem lies in the code you have shown us.
This line:
//In the class constructor:
suggests you are using this inside a class and not implementing the rule of three correctly.
A better idea is not to use a pointer to a vector.
Just declare it as a normal automatic member.
class MyClassContainingVector
{
public:
std::vector<MyObject> mvMyObjectVector;
// ^^^^^ notice no pointer.
};
Now it will be created and destroyed correctly and automatically.
Neither your constructor or destructor will need any code to manage this object.
Yes, dynamically allocating a std::vector object by calling new and invoking its destruction by calling delete will result in memory that has been internally used for holding its elements being freed.
However it would be much simpler and more reliable to follow RAII idiom and use an object with automatic storage duration:
{
std::vector<MyObject> myVector;
...
} // <-- memory is freed here
when execution leaves this scope (note that it could be also caused by exception being thrown etc.), it is guaranteed that myVector object will be destructed and memory will be freed.
Vectors usually shouldn't be held as dynamically allocated pointers. They should be just member variables of your class, in most situations (though there are always exceptions). If they are pointers allocated by 'new', and simple 'delete' should work.
Vectors handle memory allocation for you, so you don't have to. However, if you want to truly free all the storage memory held in a vector, even if it's on the stack, there's a new function for that.
Because vector.reserve() only expands memory, but never shrinks it, in C++11, a new function was added for the purpose of freeing the reserved memory: vector.shrink_to_fit(). Implementations and free to do what they want with it, but you're basically asking the implementation to free the memory, so they should answer the request in a reasonable way.
You can truly clear a vector by going like this:
vector.clear(); //Erases the elements.
vector.shrink_to_fit(); //Erases the memory no longer needed by the elements.
The reasons why vectors hold onto their memory is for performance reasons, so you should only do this if you actually understand why they have memory in reserve, and are willing to deal with (or know you won't have to deal with) any performance hits that result from micro-managing the memory.

C++ Memory Deallocation

I'm trying to test my understanding of C++ memory allocation.
For the following program:
{
int a=0;
}
Since a is allocated off the stack it should be freed when the variable goes out of scope, right?
Okay, easy enough. What about this case:
{
Matrix m(50, 20);
}
Let's say there's a matrix class and I'm creating a new one with 50 rows and 20 columns. Obviously not all of the memory can be allocated off the stack because 50 and 20 could be populated at run time. So I'm guessing that somewhere in the constructor, they allocate memory off the heap.
When that goes out of scope the destructor on m is called? And that desctructor should deallocate (delete) the memory it allocated?
Now it really gets hard:
{
Matrix t;
{
Matrix m(50, 20);
t=m;
}
}
What happens then? Does t get assigned to the memory location of m? or does it do a copy of the data in m? If t is a reference to m, then what happens when m goes out of scope? Does the destructor on m get called? or does it wait until t goes out of scope to call the destructor of t/m?
When that goes out of scope the destructor on m is called? And that
desctructor should deallocate (delete) the memory it allocated?
Yes and generally yes.
Now it really gets hard:
{
Matrix t;
{
Matrix m(50, 20);
t=m;
}
}
What happens then? Does t get assigned to the memory location of m? or does it do a copy of the data in m?
What happens is that the assignment operator is called:
t.operator=(m);
It is up to you, the implementer of Matrix, to ensure valid semantics. There are several possible approaches:
The assignment operator could make a copy of m's data. In this case there are no difficulties with lifetime and ownership. However, in this approach the assignment is costly.
The assignment operator could make t point to the same data as m. This may be viable, but will require a lot of care to make sure the lifetime of the data is managed correctly, and that modifying one matrix doesn't unexpectedly modify the other. One way to do this is by keeping a reference-counted pointer to the data, and using copy-on-write when modifying data. Some older implementations of std::string are of this type.
Actually, it's pretty easy.
In the first case, you're right. Automatic allocation, automatic deallocation.
In the second case, it's not really any different. The Matrix class constructor handles any additional memory it needs, and its destructor should deallocate it.
In the third class, the inner scope variable is copied to the outer scope variable. The Matrix class should be following the Rule of Three, so copies should be handled correctly.
All of this is assuming a proper implementation of Matrix.
C++ memory allocation is really simple, so is object scope. C++ class design is not as simple.
In your examples, each time you close a brace, the local objects, a or m or t (for the outer set of braces in your last example), go out of scope and their destructor is called. In the case of the int, the destructor is simple and deletes the object on the stack. For m, it's a custom destructor for the class Matrix and for any respectable library, you can assume it deallocates the object correctly.
What complicates t is not the destructor, but the assignment from m. In most implementations of matrix classes, t = m would result in the contents of m being copied into t, which would have its own memory on the heap. Then as each object goes out of scope, their corresponding memory is deallocated.
If the implementation is more complex, then its up to the class designer to make sure it handles the destruction of each object correctly (and you to use the library correctly so that it can).
What happens then? Does t get assigned to the memory location of m?
It's a call to copy constructor which do member wise copy by default.
but if you have overloaded an assignment operator then you can either assign the reference or create a complete new object its up to you.
for rest of the Ques:
call to destructor depends on you either you call it explicitly or leave it to default. in default it will be called when the variable or object is out of scope.
You're correct with the int. When the allocation is called, an int size amount of space is taken up on the stack, and when the variable goes out of scope, that int is "popped off" the stack and the memory is free to be used again.
With the Matrix, you're not 100% right. Just because the data is allocated at run-time, doesn't mean it can't be allocated on the stack, as long as there's room on the stack to put it. What happens here is that when you create the matrix, it is pushed onto the stack. The amount of space it takes up on the stack is dependent on how it's managed. Within its constructor, it may allocate memory to the heap, or it may simply take up a big ol' chunk of stack space. If there isn't room on the stack, you'll get a stack overflow exception at runtime.
You are correct though that if it does allocate memory at construction, it should clean it up at destruction. But it doesn't have to, and in some cases it shouldn't (e.g. if it doesn't actually "own" that memory anymore because it's given/sharing it with another object).
In your final case, what happens is this:
Matrix t;
This creates a Matrix using the default constructor of the class. Whether it reserves any memory here is dependent on what that constructor has in it. It might reserve memory, but it might not.
Matrix m(50, 20);
This creates a Matrix using a different constructor of the class. Again, it might reserve memory, but it might not (e.g. it might not take up any space other than what's on the stack till some "real" data is added to it)
t=m;
What happens here is, again, up to the class. At this point, this is not a constructor, but the assignment function of t:
Matrix& operator=(const Matrix& m){
....
}
being called. Some assignment constructors will copy the data, some will copy pointers to the data but not the actual data itself. However, in the latter case, the class should handle the condition where m goes out of scope, by refusing to delete the data, and instead relying on the constructor of t to do it. But again, they don't have to, and may do it badly (especially as controlling this gets complicated)
The critical take from this is that once you reach the level of class creation & destruction, how memory is handled is dependent on the implementation of the class.

When should objects be dynamically or automatically instantiated?

For example, should I use:
Foo* object = new Foo ;
or should I just use
Foo object ;
If I messed up the code one either of those, please correct. It is early and I am a beginner.
In the first case you allocate your Foo object in heap, while in the second it's allocated in stack.
Usually things are allocated in heap if:
Foo is so big that it wouldn't fit in the stack.
You don't know when to allocate your object (you only need to allocate it under some circumstances).
You need to extend the lifetime of your object also after the stack gets popped.
In most other cases (I could be forgetting some other common scenarios when it's useful to dynamically allocate your object) it's probably suggested to allocate your object in stack, since it will cost less at runtime and will be less error prone and easier to be handled.
operator new should be avoided wherever possible. It's wasteful in all areas - syntactically, semantically, and at run-time with space and time. If you have an object that can be allocated on the stack or statically in a class, do it. Dynamic allocation should only be used when you need exactly that - dynamism. If you don't need it to be dynamic, don't use dynamic allocation.
The default in C++ should be to use the objects themselves and not pointers (smart or otherwise) until there are specific reasons to do otherwise.
To get a default-constructed object, you must leave the parentheses off:
Foo object;
otherwise, the compiler will take it as the declaration of a function.
Automatic instantiation should be the norm since the object life-time is then determined by the scope, and destruction is automatic. Dynamic instantiation is necessary when the object is required to exist outside of the current scope.
Dynamic instantiation may also be necessary if the object is excessively large, and you have limited stack space. However for a single object this would be an unusual case, and often indicative of a design flaw.
Dynamic instantiation is more typically used for arrays of objects, when the resulting array is either too large for the stack or the size of the array is not known a priori.
The important thing to remember is that if you dynamically instantiate an object you are responsible for explicitly destroying it. Not doing so results in a memory leak.
Allocating objects with a new operator requires that you clean up after then with a delete operator. So on most cases, if it isn't necessary, I'd go with the static instantiation.
However, since the static instantiation will put the object on the stack, you might run into memory problems: the stack can only hold so much data. So sometimes it might be necessary instantiate the object dynamically.
The second usage should be:
Foo object;
The difference between the two is that the first is allocating the object on the heap, and the second is allocating the object on the stack. There are many differences, but here are a few:
When you allocate an object on the heap, it will be alive until you explicitly delete it, whereas an object allocated on the stack is only alive until the function ends.
Allocating an object on the heap is more expensive (in terms of performance) than allocating objects on the stack.
You can generally allocate many more objects on the heap than on the stack.
Objects allocated on the heap may be passed around between threads, whereas objects allocated on the stack cannot (that's not 100% correct, you can make your function stay alive while the other thread is working on your object, but that's pretty much useless and inefficient).
Objects allocated on the stack will be allocated as soon as you enter the scope where they are declared. There are cases when you don't necessarily want them to always be allocated, which is when you might prefer to use a dynamic allocation on the heap.
In C++, pointers should be used only when it is really required for you to allocate memory on heap (at runtime). One of the purposes of introducing pointers in C was to be able to pass by address so that the object to be modified could be passed as parameter. In C++, you can achieve that by passing References to objects.