I have some background in Java (and recently in C#) and would like to get to know C++ better as well. I think I'm aware of some of the basics of the differences in memory (and other resource) management between these languages. This is perhaps a small question relating to using the dispose pattern and the different features available in these languages to assist with it. I like what I've gathered of the RAII and SBRM principles and I'm trying to understand them further.
Suppose I have the following class and method in Java
class Resource implements Closeable {
public void close() throws IOException {
//deal with any unmanaged resources
}
}
...
void useSomeResources() {
try(Resource resource = new Resource()) {
//use the resource
}
//do other things. Resource should have been cleaned up.
}
or a fairly close C# analogue
class Resource : IDisposable
{
public void Dispose()
{
//deal with any unmanaged resources
}
}
...
void UseSomeResources()
{
using(var resource = new Resource())
{
//use the resource
}
//do other things. Resource should have been cleaned up.
}
Am I right to think that the idiom best representing this same behaviour in C++ would be the following?
class Resource {
~Resource() {
cleanup();
}
public:
void cleanup() {
//deal with any non-memory resources
}
};
...
void useSomeResources()
{
{
Resource resource;
//use the resource
}
//do other things. Stack allocated resource
//should have been cleaned up by stack unwinding
//on leaving the inner scope.
}
I don't want, especially, to elicit debate over whose language is better and things like that, but I'm wondering to what extent these implementations can be compared, and how robust they all are to cases where the block using the resource encounters exceptional circumstances. I may have completely missed the point on something, and I'm never quite sure about best practices for disposal - for the sake of argument, perhaps it's worth assuming all disposal/destruction functions here are idempotent - and really good tips for those matters might also be relevant to this question.
Thanks for any pointers.
It's almost the pattern. In fact you don't need to add a cleanup()
function: the destructor is there to do the cleanup.
By the way, having a public cleanup()
exposed, allows for accidental call of cleanup()
, bringing the ressource in an undesired state.
class Resource {
~Resource() {
//deal with any non-memory resources
}
}; // allways ; at the end of a class ;-)