Reputation: 24759
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?
Upvotes: 2
Views: 102
Reputation: 20393
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.
Upvotes: 0
Reputation: 61970
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
Upvotes: 5