Name convention for deleting data in C++
Assume I have some C++ method which returns back a pointer to an object. Something in the header file that looks lik开发者_运维问答e this:
uint8_t* getData(void);
This guy returns a byte array, but there is nothing that says if this is a dynamic or statically generated piece of data (local to the class or created with new).
Is there a specific naming convention in C++ to distinguish between methods that return memory that is dynamically allocated (and so must be deleted by the requester), vs methods that just return a reference to a statically define piece of data?
What is the preferred way to do this, or does it depend on the situation?
In C++, you simply do not hand out raw pointers to clients in the first place. One possible solution:
std::vector<uint8_t> getData();
EDITED !
If you return pointer to a locally allocated array, the program will crash when you try to use this pointer, as after exiting from the function, the array will be destroyed. Actually, a crash will be the best behavior, because this situation is undefined behavior. Here's why - you return a address of something, that is not existing anymore. So, the best think that could happen is a crash (after you try to use it anyhow). The other option is this address to be an address of another object in your program (you don't know which one), so if you try to modify it.. it's really bad thing.
The other variant - returning pointer to array, that's allocated with "new" is very dangerous and it's a potential memory leak. So, use smart pointers - it's the best way (: /* see Roger Pate's comment at this question about usage of smart pointers */
The other way is to return a copy of the array (using std::vector), but it's very slow (if you're array is big, especially when the array is from some big user-defined type), and it's not really good idea in the most cases.
// Thanks to ybungalobill, Steve and Roger Pate for their remarks!
My conventions are:
uint8_t* getData();
is statically allocated, or at least it's not my responsibility for deleting this data. However if it's an array I would write:
pair<uint8_t*,uint8_t*> getData();
Or define a container for that.
auto_ptr<uint8_t> getData();
unique_ptr<uint8_t> getData();
allocates single object and I own it from now on.
shared_ptr<uint8_t> getData();
allocates single object with shared ownership.
vector<uint8_t> getData();
allocates an array, vector owns the memory.
Put it in the documentation.
Indeed - it's very rare that you would actually want to return a pointer to non-dynamically allocated memory. I don't believe it will actually cause a program crash - once I wrote a threading library which used array declarations to inflate the run-time stack and store space for threads; the fact that the memory it's pointing to can change at random is what's dangerous.
If it is the client's responsibility to manage the memory returned, then some form of wrapping class should be used that handles this responsibility. When using an array you should almost always return a std::vector, because this will also manage the array aspects such as the size, resizing, etc, but for a raw pointer you should typically use a std::auto_ptr or std::shared_ptr. If you're writing a module intended to be used between compilers, write your own. It's easy to return a proxy object that can be converted into various brands of smart pointer.
One cannot return static data pointer
or of local variable since as the stack unwinds the object destructs.
It has to be dynamically allocated and it's always the callers responsibility to free
it since the function doesn't know when to free it.
Also, please keep in mind, many functions need special deallocaters and doing delete or delete[] is not always the right option. You might end up corrupting the heap! Read the function documentation for that info.
If the functions return pointers, then use getData
for getting access to memory without taking ownership of it and adoptData
for access and taking ownership. At least that's the convention I've seen used most often.
But as others have said, return a container, smart pointer or something else that will automatically handle the memory. RAII is your friend.
And don't forget to state in the API docs of both functions if they transfer ownership or not. The convention is great for people who know it, but it still has to be convenient for those who don't.
In Clang there is a simple convention (check it out here):
getX
returns a pointer, not ownershiptakeX
returns both pointer and ownership
However, as has been noted, I would lift the compiler abilities here and return a smart manager (smart pointer, container, whatever) rather than a naked pointer when returning ownership.
It's way too easier to let a memory leak slip in when all you have to help is a naming convention... you can still keep the naming convention though ;)
As many have said, don't return a raw pointer. If you want the data to be deleted by the requester (for some reason), you can use something like shared_ptr
or auto_ptr
, in which case the caller cleans up the returned value (weather he wants to or not). If instead you are returning a member of some class that doesn't get cleaned up, then don't return a pointer at all, return a (possibly const) reference.
精彩评论