I'm studying C++ now. It is a so complicated language that I'm not sure which feature I should use and when to use.
C++ Primer introduces RAII as a method to ensure exception safety. Does that mean, as a good behavior, when I want to use an array, I should put array into an class to allocate and destroy resources. I know my idea is very simple, or naive.
I'm just curious about what is good C++ coding behavior.
RAII means that a resource is tied to the object lifetime.
Every STL class of C++ follows this principle, this means that if you need an array you can simply use std::vector.
The destructor of the vector class will take care of deleting the resources when your instance goes out of the scope.
This means that in your case, instead of using new like this:
int *array = new int[n];
you should use:
vector<int> array(n);
If you really need to allocate on the heap to have a shared pointer and still be safe by using RAII you can do (requires C++11):
shared_ptr<vector<int>> array(new vector<int>(10));
It depends how you create your array. If you create it in some block of code like this
int arr[5];
it has automatic storage. This array is automatically destroyed when it goes out of scope.
The only time you have to explicitly manage the lifetime of your objects is if you dynamically allocate them, perhaps like so:
int* arr = new int[5];
This allocates an array of 5 ints which need to be manually deleted later like this:
delete[] arr;
RAII is the idea that we can have a class's constructor perform the dynamic allocation and its destructor perform the deallocation. Then if we create objects of this class type, they will internally perform dynamic allocation, but we can be sure that the memory will be correctly deallocated when finished with.
So yes, if you really want a dynamically allocated array, you could encapsulate it in your own class. However, this already exists in a more powerful form: std::vector. The std::vector type internally manages a dynamically allocated array, but also allows you to add elements to and remove elements from it at run-time.
Note that this isn't something specific to arrays. Best practice is to encapsulate all dynamic allocation (even a simple new int) within classes. The standard library provides many classes to help you do this (in particular, smart pointers).
RAII is a recommended idiom for resource management -- resources can be threads, memory... I frequently encounter long-time developers who don't understand RAII or how to use it, so there's no shame in asking. Unfortunately, I think you need a little background and terminology to understand it. In C++ you can create objects in one of two kinds of memory: The stack and the heap.
The Stack:
Consider this code:
class Foo
{
// some implementation
}
void bar()
{
Foo f;
// do something with f.
// maybe it throws an exception, maybe not.
}
Here the object f of type Foo has been created on the stack. When the running program leaves the scope in which f was created (in our example when it leaves the function bar()), f's destructor will called, regardless of how it leaves the scope. It might leave scope because the function executed successfully, or it might leave scope because an exception was thrown.
Heap allocation
Now consider the following:
class Foo
{
// same thing
}
void bar()
{
Foo* f = new f;
// whatever
delete f;
}
In this case we created the object f on the heap. You can tell we did so because we called the new operator. Whenever an object is created with new, we have to call delete in order to free the memory up. This can be error prone, because people forget to call delete, or they return the pointer and it's unclear where the pointer should get deleted, or because an exception is thrown. RAII is a solution to all those, and it should be your first tool of choice.
But that doesn't mean you should put your arrays in a class (well it kind of does in some circumstances, but probably not in the way that you mean). Consider the following:
void foo()
{
// c-style array, but fixed size.
int bar_stack[5];
// c-style array, dynamically allocated!
unsigned int array_size = get_array_size();
int* bar_heap = new int[array_size]
// c++ way:
std::vector bar_vector(array_size);
}
In the first example we have a fixed c-style array, it's allocated on the stack, so it's nothing to worry about. In the second case, it's dynamically allocated (the compiler doesn't know the size, its available at run time), so we would need a delete, meaning we'd need to protect against exceptions and make sure there's a clear owner. In the third case we just use a vector, which is a standard container.
Now I provided all that because I was afraid you wouldn't understand the short answer which is: Yes you should generally use RAII to manage your resources, but you should use std containers, not arrays. Why? Because std containers provide RAII for you -- unless you make a container of pointers, or allocate your vector on the heap.
I hope that helps.
Related
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.
I'm not normally a C++ developer. My usual languages are all garbage collected and they do the work for me, but C++ interests me.
There's a question or two I have about returning dynamically allocated objects or structs. It's my understanding that they have to be dynamically allocated so the data is in the heap and not the stack. Please, correct me if I'm wrong.
What is the best practice to return pointers? Say I'm writing a library, how do I indicate in code if/when returned pointers should be deleted? If I'm returning an array, how do I return the size of the array?
These aren't problems I have to face in C# or javascript. These questions do go both ways: if I'm using somebody else's library, what do I look for?
C++ has an idiom called RAII. What it means for you is that you won't have to worry about cleaning up, and the resource will be freed at a defined point in the code.
For example, making an array in a function and returning it. Here's one typical implementation without RAII (another being the caller allocating memory and passing it in):
int *makeIntArray(std::size_t length) {
return new int[length];
}
Now the caller needs to remember to free this memory. Compare this with an RAII version:
std::vector<int> makeIntArray(std::size_t length) {
return std::vector<int>(length);
}
What is returned from this will have its memory deallocated when the vector goes out of scope, which is up to the caller. It also provides, among others, a size() member function to obtain the number of elements.
That said, it's best to keep things not dynamically allocated when possible. If you need to return a structure, say Str, just return it by value:
Str makeStr() {
return Str();
}
No dynamic allocation means no extra work, whether to free the memory, or wrap it in something (a smart pointer such as std::unique_ptr in this case).
As for other libraries, you need to read the documentation to ensure you must own what it returns. If you must, one thing you can do is make an RAII object out of it. For example:
int *makeSomeInt(int value) {
return new int(value);
}
...
std::unique_ptr<int> myInt(makeSomeInt(5));
//memory freed when myInt goes out of scope
I see chris has already provided a nice answer. Few things to add to that:
Stay away from allocating dynamic memory in your code. Let the dynamic memory allocation (and deallocation) be done by the library as much as possible. (See the example of vector above.)
If you must do dynamic memory allocation by yourself, then every memory (i.e. pointer) must have a owner. It is the owner who should construct and destruct the memory, others can only use it.
If you are using C++11, then familiarize yourself to unique_ptr, that is the one you would most commonly need.
From Dr.Dobbs:
There are a lot of great features in C++11, but unique_ptr stands out
in the area of code hygiene. Simply put, this is a magic bullet for
dynamically created objects.
What's a good policy for when to use "new" to make an instance of a class? I've been hobby programming C++ for a while but I'm still not for sure when is the best time to do this:
MyClass thing(param1, param2);
over this:
MyClass* thing;
thing = new MyClass(param1, param2);
Any advice?
Design-wise, use automatic (stack) allocation as much as possible. Whenever you need to extend the lifetime of an object beyond a certain scope, then dynamically allocate it.
And even so, never dynamically allocate things raw. Always keep them wrapped into some sort of wrapper that implements Scope-Bound Resource Management (SBRM, first known under the dumb/awkward name Resource-Acquisition Is Initialization or RAII.) That is, dynamic allocations should be kept in automatic objects that will clean up automatically!
A good example of this is std::vector: you cannot leak the memory internal to a vector, because it's destructor is run in every scenario when memory should be free'd, and it will free it for you. auto_ptr is the first and only smart pointer available in the standard library, but it's pretty bad. Better is to use shared_ptr, or many of the other popular smart pointers available in Boost and/or TR1 and/or C++0x.
Performance-wise, objects allocated on the stack can be done so very quickly (the stack size is increased per-function-call, so all the required memory has been allocated up-front by a simple move of a pointer.) Contrarily, dynamic allocation generally requires much more time. It's quite possible to get speedy dynamic allocations with custom allocation schemes, but even the best will still be slower than stack allocation.
Occasionally, you might find you spend too much time copying objects around. In this case, it may be worth it to dynamically allocate it and merely move pointers around. However, please note I said "find". This kind of change is something you find by profiling and measuring, never guessing.
So: Automatic allocation when possible, dynamic allocation when needed.
The first approach creates a local instance on the stack that goes away when the calling function exits. The second creates an instance that stays on the heap until (and if) you explicitly release it again. The choice depends on what kind of control and lifetime you want for your object.
The rule of thumb is: if it works without new, don't use new.
In general: you don't need to use new if you plan to delete the object in the same scope. If the object is quite large, you may want to use new.
You may want to look into the difference between heap and stack memory if you want to know the details.
First, ask yourself the question, does it make sense for the object to be copied when another function wants it?
If it makes sense to copy the object, your best bet is to create everything on the stack or as member variables and then just pass copies around when needed.
If it does not make sense to copy the object, you'll need to use new form so that you can safely pass the pointer to the object. You have to use a pointer (or reference) because as noted it does not make sense to copy the object.
There are two exceptions I'm aware of:
If you know the object isn't going to be used after the current function is finished, you can create the object on the stack so that it is deleted. Just make very sure nobody holds on to a pointer to it afterwards! (I rarely find this is the case, but it happens)
If the object is used internally by another class which itself shouldn't be copied around, you can just put it in as a member variable. Since the object it is in won't be copied, and its only for internal use that will be safe.
MyClass thing(param1, param2); //memory for thing is allocated on the process stack(static allocation)
MyClass* thing;
thing = new MyClass(param1, param2); //memory is allocated dynamically on the heap(free store) for thing
The difference lies here:
int main()
{
{
MyClass thing(param1, param2); //thing is local to the scope
} //destructor called for thing
//cannot access thing (thing doesn't exist)
}
int main()
{
{
MyClass* thing;
thing = new MyClass(param1, param2);
}
//the object pointed to by thing still exists
//Memory leak
}
For large objects you must allocate memory dynamically(use new) because the process stack has a limited size.
I am writing a template class that takes as an input a pointer and stores it. The pointer is meant to point to an object allocated by another class, and handed to the this containing class.
Now I want to create a destructor for this container. How should I free the memory pointed to by this pointer? I have no way of knowing a priori whether it is an array or a single element.
I'm sort of new to C++, so bear with me. I've always used C, and Java is my OO language of choice, but between wanting to learn C++ and the speed requirements of my project, I've gone with C++.
Would it be a better idea to change the container from a template to a container for an abstract class that can implement its own destructor?
If you don't know whether it was allocated with new or new[], then it is not safe to delete it.
Your code may appear to work. For example, on one platform I work on, the difference only matters when you have an array of objects that have destructors. So, you do this:
// by luck, this works on my preferred platform
// don't do this - just an example of why your code seems to work
int *ints = new int[20];
delete ints;
but then you do this:
// crashes on my platform
std::string *strings = new std::string[10];
delete strings;
You must document how this class expects to be used, and always allocate as expected. You can also pass a flag to the object specifying how it should destroy. Also look at boost's smart pointers, which can handle this distinction for you.
Short answer:
If you use [] with new you want to use [] with delete.
//allocate some memory
myObject* m = new myObject[100];
//later on...destructor...
delete m; //wrong
delete[] m; //correct
That was the bare bones, the other thing you could look at is boost. Also quite difficult to answer considering you are not sure if its an array or single object. You could check this though via a flag telling your app whether to use delete or delete[].
As a general development rule, you should stick to a design where the class which calls new should also call delete
You shouldn't delete it at all. If your class takes an already initialized pointer, it is not safe to delete it. It might not even point to an object on the heap; calling either delete or delete[] could be disastrous.
The allocation and deallocation of memory should happen in the same scope. Which ever code owns and initializes the instance of your class is also presumably responsible for initializing and passing in the pointer, and that is where your delete should be.
Use delete if you allocated with new.
Use delete[] if you allocated with new[].
After these statements, if you still have a problem (maybe you want to delete an object that was created by someone else), then you are breaking the third rule:
Always delete what you created. Corollary, never delete what you did not create.
(Moving my comment into an answer, by request.)
JonH's answer is right (about using array destruction only when you used array construction), so perhaps you should offer templates: one for arrays, one not.
The other answer is to avoid arrays and instead expect a single instance that may or may not be a proper collection that cleans up after itself, such as vector<>.
edit
Stealing blatantly from Roger Pate, I'll add that you could require the use of a smart pointer, which amounts to a single-item collection.
If you have a class that takes a pointer it's going assume ownership of, then the contract for the use of the class needs to include one of a couple things. Either:
the interface needs to indicate how the object the pointer is pointing to was allocated so the new owner can know how to safely deallocate the object. This option has the advantage of keeping things simple (on one level anyway), but it's not flexible - the class can't handle taking ownership of static objects as well as dynamically allocated objects.
or
the interface needs to include a mechanism where a deallocation policy can be specified by whatever is giving the pointer to the class. This can be as simple as providing a mechanism to pass in a functor (or even a plain old function pointer) that will be called to deallocate the object (preferably in the same function/constructor that passes in the pointer itself). This makes the class arguably more complicated to use (but having a default policy of calling delete on the pointer, for example, might make it as easy to use as option 1 for the majority of uses). Now if someone wants to give the class a pointer to a statically allocated object, they can pass in a no-op functor so nothing happens when the class wants to deallocates it, or a functor to a delete[] operation if the object was allocated by new[], etc.
Since pointer in C++ does not tell us how it was allocated, yes, there's no way to decide what deallocation method to use. The solution is to give the choice to the user that hopefully knows how the memory was allocated. Take a look at Boost smart ptr library, especially at shared_ptr constructor with second parameter, for a great example.
A smart pointer like boost shared_pointer already has this covered, could you use it? linky
Put simply, given only a pointer to dynamically allocated memory there is no way of determining how to de-allocate it safely. The pointer could have been allocated in any of the the following ways:
using new
using new []
using malloc
using a user defined function
etc.
In all cases before you can deallocate the memory you have to know how it was allocated.
I'm a C programmer trying to understand C++. Many tutorials demonstrate object instantiation using a snippet such as:
Dog* sparky = new Dog();
which implies that later on you'll do:
delete sparky;
which makes sense. Now, in the case when dynamic memory allocation is unnecessary, is there any reason to use the above instead of
Dog sparky;
and let the destructor be called once sparky goes out of scope?
Thanks!
On the contrary, you should always prefer stack allocations, to the extent that as a rule of thumb, you should never have new/delete in your user code.
As you say, when the variable is declared on the stack, its destructor is automatically called when it goes out of scope, which is your main tool for tracking resource lifetime and avoiding leaks.
So in general, every time you need to allocate a resource, whether it's memory (by calling new), file handles, sockets or anything else, wrap it in a class where the constructor acquires the resource, and the destructor releases it. Then you can create an object of that type on the stack, and you're guaranteed that your resource gets freed when it goes out of scope. That way you don't have to track your new/delete pairs everywhere to ensure you avoid memory leaks.
The most common name for this idiom is RAII
Also look into smart pointer classes which are used to wrap the resulting pointers on the rare cases when you do have to allocate something with new outside a dedicated RAII object. You instead pass the pointer to a smart pointer, which then tracks its lifetime, for example by reference counting, and calls the destructor when the last reference goes out of scope. The standard library has std::unique_ptr for simple scope-based management, and std::shared_ptr which does reference counting to implement shared ownership.
Many tutorials demonstrate object
instantiation using a snippet such as ...
So what you've discovered is that most tutorials suck. ;)
Most tutorials teach you lousy C++ practices, including calling new/delete to create variables when it's not necessary, and giving you a hard time tracking lifetime of your allocations.
Though having things on the stack might be an advantage in terms of allocation and automatic freeing, it has some disadvantages.
You might not want to allocate huge objects on the Stack.
Dynamic dispatch! Consider this code:
#include <iostream>
class A {
public:
virtual void f();
virtual ~A() {}
};
class B : public A {
public:
virtual void f();
};
void A::f() {cout << "A";}
void B::f() {cout << "B";}
int main(void) {
A *a = new B();
a->f();
delete a;
return 0;
}
This will print "B". Now lets see what happens when using Stack:
int main(void) {
A a = B();
a.f();
return 0;
}
This will print "A", which might not be intuitive to those who are familiar with Java or other object oriented languages. The reason is that you don't have a pointer to an instance of B any longer. Instead, an instance of B is created and copied to a variable of type A.
Some things might happen unintuitively, especially when you are new to C++. In C you have your pointers and that's it. You know how to use them and they do ALWAYS the same. In C++ this is not the case. Just imagine what happens, when you use a in this example as an argument for a method - things get more complicated and it DOES make a huge difference if a is of type A or A* or even A& (call-by-reference). Many combinations are possible and they all behave differently.
Well, the reason to use the pointer would be exactly the same that the reason to use pointers in C allocated with malloc: if you want your object to live longer than your variable!
It is even highly recommended to NOT use the new operator if you can avoid it. Especially if you use exceptions. In general it is much safer to let the compiler free your objects.
I've seen this anti-pattern from people who don't quite get the & address-of operator. If they need to call a function with a pointer, they'll always allocate on the heap so they get a pointer.
void FeedTheDog(Dog* hungryDog);
Dog* badDog = new Dog;
FeedTheDog(badDog);
delete badDog;
Dog goodDog;
FeedTheDog(&goodDog);
Treat heap as a very important real estate and use it very judiciously. The basic thumb rule is to use stack whenever possible and use heap whenever there is no other way. By allocating the objects on stack you can get many benefits such as:
(1). You need not have to worry about stack unwinding in case of exceptions
(2). You need not worry about memory fragmentation caused by the allocating more space than necessary by your heap manager.
The only reason I'd worry about is that Dog is now allocated on the stack, rather than the heap. So if Dog is megabytes in size, you may have a problem,
If you do need to go the new/delete route, be wary of exceptions. And because of this you should use auto_ptr or one of the boost smart pointer types to manage the object lifetime.
There's no reason to new (on the heap) when you can allocate on the stack (unless for some reason you've got a small stack and want to use the heap.
You might want to consider using a shared_ptr (or one of its variants) from the standard library if you do want to allocate on the heap. That'll handle doing the delete for you once all references to the shared_ptr have gone out of existance.
There is an additional reason, which no one else has mentioned, why you might choose to create your object dynamically. Dynamic, heap based objects allow you to make use of polymorphism.
I had the same problem in Visual Studio. You have to use:
yourClass->classMethod();
rather than:
yourClass.classMethod();