Related
I was reading an article that stated due to something called RAII, you no longer needed to cleanup your code.
What prompted this research was I am currently coding something that requires cleanup before exiting the function.
For example, I have created a file, and mapped a view of a file.
Normally, I'd just use goto or do {break;} while(false); to exit. However, is it true this is no longer necessary with C++11?
I.e. no more
if( fail ) {
UnmapViewOfFile(lpMapView);
CloseHandle(hFileMap);
CloseHandle(hFile);
}
every few lines of code?
Does the compiler automatically wrap this up once the function exits? It just seems hard to believe that it actually cleans up function calls like the article said it did. (I may have misinterpreted it somehow.) What seems more likely is that it just cleans up created class libraries by calling their deconstructor from the C++ library.
EDIT: The article - from Wikipedia:
It doesn't necessarily state that it cleans up these function calls, but it does imply it does for C++ library function objects (such as FILE * , fopen, etc objects)
Does it work for WinAPI too?
C++ standard surely says nothing about usage of windows API functions like UnmapViewOfFile or CloseHandle. RAII is a programming idiom, you can use it or not, and its a lot older than C++11.
One of the reasons why RAII is recomended is that it makes life easier when working with exceptions. Destructors will always safely release any resources - mostly memory, but also handles. For memory your have classes in standard library, like unique_ptr and shared_ptr, but also vector and lots of other. For handles like those from WinAPI, you must write your own, like:
class handle_ptr {
public:
handle_ptr() {
// aquire handle
}
~handle_ptr() {
// release
}
}
Cleanup is still necessary, but due to the possibility of exceptions the code should not do cleanup simply by executing cleanup operations at the end of a function. That end may never be reached! Instead,
Do cleanup in destructors.
In C++11 it is particularly easy to any kind of cleanup in a destructor without defining a custom class, since it's now much easier to define a scope guard class. Scope guards were invented by Petru Marginean, who with Andrei Alexandrescu published an article about it in DDJ. But that original C++03 implementation was pretty complex.
In C++11, a bare bones scope guard class:
class Scope_guard
: public Non_copyable
{
private:
function<void()> f_;
public:
void cancel() { f_ = []{}; }
~Scope_guard()
{ f_(); }
Scope_guard( function<void()> f )
: f_( move( f ) )
{}
};
where Non_copyable provides move assignment and move construction, as well as default construction, but makes copy assignment and copy construction private.
Now right after successfully acquiring some resource you can declare a Scope_guard object that will guaranteed clean up at the end of the scope, even in the face of exceptions or other early returns, like
Scope_guard unmapping( [&](){ UnmapViewOfFile(lpMapView); } );
Addendum:
I should better also mention the standard library smart pointers shared_ptr and unique_ptr, which take care of pointer ownership, calling a deleter when the number of owners goes to 0. As the names imply they implement respectively shared and unique ownership. Both of them can take a custom deleter as argument, but only shared_ptr supports calling the custom deleter with the original pointer value when the smart pointer is copied/moved to base class pointer.
Also, I should better also mention the standard library container classes such as in particular vector, which provides a dynamic size copyable array, with automatic memory management, and string, which provides much the same for the particular case of array of char uses to represent a string. These classes free you from having to deal directly with new and delete, and get those details right.
So in summary,
use standard library and/or 3rd party containers when you can,
otherwise use standard library and/or 3rd party smart pointers,
and if even that doesn't cut it for your cleanup needs, define custom classes that do cleanup in their destructors.
As #zero928 said in the comment, RAII is a way of thinking. There is no magic that cleans up instances for you.
With RAII, you can use the object lifecycle of a wrapper to regulate the lifecycle of legacy types such as you describe. The shared_ptr<> template coupled with an explicit "free" function can be used as such a wrapper.
As far as I know C++11 won't care of cleanup unless you use elements which would do. For example you could put this cleaning code into the destructor of a class and create an instance of it by creating a smart-pointer. Smart-pointers delete themselves when they are not longer used or shared. If you make a unique-pointer and this gets deleted, because it runs out of scope then it automatically calls delete itself, hence your destructor is called and you don't need to delete/destroy/clean by yourself.
See http://www.cplusplus.com/reference/memory/unique_ptr/
This is just what C++11 has new for automatically cleaning. Of course an usual class instance running out of scope calls its destructor, too.
No!
RAII is not about leaving clean-up aside, but doing it automatically. The clean-up can be done in a destructor call.
A pattern could be:
void f() {
ResourceHandler handler(make_resource());
...
}
Where the ResourceHandler is destructed (and does the clean-up) at the end of the scope or if an exception is thrown.
The WIN32 API is a C API - you still have to do your own clean up. However nothing stops you from writing C++ RAII wrappers for the WIN32 API.
Example without RAII:
void foo
{
HANDLE h = CreateFile(_T("C:\\File.txt"), FILE_READ_DATA, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL);
if ( h != INVALID_HANDLE_VALUE )
{
CloseHandle(h);
}
}
And with RAII:
class smart_handle
{
public:
explicit smart_handle(HANDLE h) : m_H(h) {}
~smart_handle() { if (h != INVALID_HANDLE_VALUE) CloseHandle(m_H); }
private:
HANDLE m_H;
// this is a basic example, could be implemented much more elegantly! (Maybe a template param for "valid" handle values since sometimes 0 or -1 / INVALID_HANDLE_VALUE is used, implement proper copying/moving etc or use std::unique_ptr/std::shared_ptr with a custom deleter as mentioned in the comments below).
};
void foo
{
smart_handle h(CreateFile(_T("C:\\File.txt"), FILE_READ_DATA, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL));
// Destructor of smart_handle class would call CloseHandle if h was not NULL
}
RAII can be used in C++98 or C++11.
I really liked the explanation of RAII in The C++ Programming Language, Fourth Edition
Specifically, sections 3.2.1.2, 5.2 and 13.3 explain how it works for managing leaks in the general context, but also the role of RAII in properly structuring your code with exceptions.
The two main reasons for using RAII are:
Reducing the use of naked pointers that are prone to causing leaks.
Reducing leaks in the cases of exception handling.
RAII works on the concept that each constructor should secure one and only one resource. Destructors are guaranteed to be called if a constructor completes successfully (ie. in the case of stack unwinding due to an exception being thrown). Therefore, if you have 3 types of resources to acquire, you should have one class per type of resource (class A, B, C) and a fourth aggregate type (class D) that acquires the other 3 resources (via A, B & C's constructors) in D's constructor initialization list.
So, if resource 1 (class A) succeeded in being acquired, but 2 (class B) failed and threw, resource 3 (class C) would not be called. Because resource 1 (class A)'s constructor had completed, it's destructor is guaranteed to be called. However, none of the other destructors (B, C or D) will be called.
It does NOT cleanup `FILE*.
If you open a file, you must close it. I think you may have misread the article slightly.
For example:
class RAII
{
private:
char* SomeResource;
public:
RAII() : SomeResource(new char[1024]) {} //allocated 1024 bytes.
~RAII() {delete[] SomeResource;} //cleaned up allocation.
RAII(const RAII& other) = delete;
RAII(RAII&& other) = delete;
RAII& operator = (RAII &other) = delete;
};
The reason it is an RAII class is because all resources are allocated in the constructor or allocator functions. The same resource is automatically cleaned up when the class is destroyed because the destructor does that.
So creating an instance:
void NewInstance()
{
RAII instance; //creates an instance of RAII which allocates 1024 bytes on the heap.
} //instance is destroyed as soon as this function exists and thus the allocation is cleaned up
//automatically by the instance destructor.
See the following also:
void Break_RAII_And_Leak()
{
RAII* instance = new RAII(); //breaks RAII because instance is leaked when this function exits.
}
void Not_RAII_And_Safe()
{
RAII* instance = new RAII(); //fine..
delete instance; //fine..
//however, you've done the deleting and cleaning up yourself / manually.
//that defeats the purpose of RAII.
}
Now take for example the following class:
class RAII_WITH_EXCEPTIONS
{
private:
char* SomeResource;
public:
RAII_WITH_EXCEPTIONS() : SomeResource(new char[1024]) {} //allocated 1024 bytes.
void ThrowException() {throw std::runtime_error("Error.");}
~RAII_WITH_EXCEPTIONS() {delete[] SomeResource;} //cleaned up allocation.
RAII_WITH_EXCEPTIONS(const RAII_WITH_EXCEPTIONS& other) = delete;
RAII_WITH_EXCEPTIONS(RAII_WITH_EXCEPTIONS&& other) = delete;
RAII_WITH_EXCEPTIONS& operator = (RAII_WITH_EXCEPTIONS &other) = delete;
};
and the following functions:
void RAII_Handle_Exception()
{
RAII_WITH_EXCEPTIONS RAII; //create an instance.
RAII.ThrowException(); //throw an exception.
//Event though an exception was thrown above,
//RAII's destructor is still called
//and the allocation is automatically cleaned up.
}
void RAII_Leak()
{
RAII_WITH_EXCEPTIONS* RAII = new RAII_WITH_EXCEPTIONS();
RAII->ThrowException();
//Bad because not only is the destructor not called, it also leaks the RAII instance.
}
void RAII_Leak_Manually()
{
RAII_WITH_EXCEPTIONS* RAII = new RAII_WITH_EXCEPTIONS();
RAII->ThrowException();
delete RAII;
//Bad because you manually created a new instance, it throws and delete is never called.
//If delete was called, it'd have been safe but you've still manually allocated
//and defeated the purpose of RAII.
}
fstream always did this. When you create an fstream instance on the stack, it opens a file. when the calling function exists, the fstream is automatically closed.
The same is NOT true for FILE* because FILE* is NOT a class and does NOT have a destructor. Thus you must close the FILE* yourself!
EDIT: As pointed out in the comments below, there was a fundamental problem with the code above. It is missing a copy constructor, a move constructor and assignment operator.
Without these, trying to copy the class would create a shallow copy of its inner resource (the pointer). When the class is destructed, it would have called delete on the pointer twice! The code was edited to disallow copying and moving.
For a class to conform with the RAII concept, it must follow the rule for three: What is the copy-and-swap idiom?
If you do not want to add copying or moving, you can simply use delete as shown above or make the respective functions private.
I'm currently in charge of finding all bad practices in our code base and to convince my colleagues to fix the offending code. During my spelunking, I noticed that many people here use the following pattern:
class Foo
{
public:
Foo() { /* Do nothing here */ }
bool initialize() { /* Do all the initialization stuff and return true on success. */ }
~Foo() { /* Do all the cleanup */ }
};
Now I might be wrong, but to me this initialize() method thing is awful. I believe it cancels the whole purpose of having constructors.
When I ask my collegues why this design decision was made, they always answer that they have no choice because you can't exit a constructor without throwing (I guess they assume throwing is always bad).
I failed to convince them so far and I admit I may lack of valuable arguments... so here is my question: Am I right that this construct is a pain and if so, what issues do you see in it ?
Thank you.
Both single step (constructor) initialisation and two step (with an init method) initialisation are useful patterns. Personally I feel that excluding either is a mistake, although if your conventions prohibit use of exceptions entirely then you prohibit single step initialisation for constructors that can fail.
In general I prefer single step initialisation because this means that your objects can have
stronger invariants. I only use two step initialisation when I consider it meaningful or useful for an object to be able to exist in an "uninitialised" state.
With two step initialisation it is valid for your object to be in an uninitialised state - so every method that works with the object needs to be aware of and correctly handle the
fact that it might be in an uninitialised state. This is analogous to working with pointers, where it is poor form to assume that a pointer is not NULL. Conversely, if you do all your initialisation in your constructor and fail with exceptions than you can add 'the object is always initialised' to your list of invariants, and so it becomes easier and safer to
make assumptions about the state of the object.
This is usually known as Two phase or Multiphase Initialization and it is particularly bad because once a constructor call has finished successfully, you should have a ready to use object, In this case you won't have a ready-to-use object.
I cannot help but stress more on the following:
Throwing an exception from constructor in case of failure is the best and the only concise way of handling object construction failures.
It depends on the semantics of your object. If the initialization is something that's crucial to the data structure of the class itself, then a failure would be better handled by either throwing an exception from the constructor (e.g. if you are out of memory), or by an assertion (if you know that your code should not actually fail, ever).
On the other hand, if success or otherwise of the construction depends on user input, then failure is not an exceptional condition, but rather part of the normal, expected runtime behaviour that you need to test for. In that case, you should have a default constructor that creates an object in an "invalid" state, and an initialization function that can be called either in a constructor or later and that may or may not succeed. Take std::ifstream as an example.
So a skeleton of your class could look like this:
class Foo
{
bool valid;
bool initialize(Args... args) { /* ... */ }
public:
Foo() : valid(false) { }
Foo(Args... args) : valid (false) { valid = initialize(args...); }
bool reset(Args... args) // atomic, doesn't change *this on failure
{
Foo other(args...);
if (other) { using std::swap; swap(*this, other); return true; }
return false;
}
explicit operator bool() const { return valid; }
};
It depends on the case.
If a constructor can fail because of some arguments, an exception should be thrown. But, of course, you need to document yourself on throwing exceptions from constructors.
If Foo contains objects, they will be initialized twice, once in the constructor, once in the initialize method, so that's a drawback.
IMO, the biggest drawback is that you have to remember to call initialize. What's the point of creating an object if it's invalid?
So, if their only argument is that they don't want to throw exceptions from the constructor, it's a pretty bad argument.
If, however, they want some sort of lazy initialization, it's valid.
It is a pain, but you have no other choice if you want to avoid throwing exception from constructor. There is also another option, equally painful: do all initialization in the constructor and then you have to check if the object has been constructed succefully (e.g. conversion operator to bool or IsOK method). Life is hard, ..... and then you die :(
I realise this is a very old thread, but I wanted to add something that hasn't been explicitly stated (or is perhaps simply implied). In C++, when a constructor throws an exception, the object is not considered "constructed" and therefore its destructor will not get called as part of the exception unwinding.
This can be a very real motivating factor for having an initialise( ) method instead of doing it in the constructor. A complex object doing lots of memory allocation and the like would have to unwind all that work manually if the constructor threw an exception.
If an initialise( ) method is used, the object is already "constructed" at the time of initialisation, and hence the object's destructor will be called.
So, yes, doing the initialisation in the constructor is "nicer", but it also puts a greater burden on the programmer to clean up properly if things go wrong. A piecemeal approach to cleaning up will make for very ugly code.
In some cases, therefore, it might be better to accept pragmatism over idealism.
When an object is constructed, it must be ready to use.
most SDK developers forgot this rule, and they expect to call another method named initialize to complete setup because they have to do some async tasks to construct object, but problem is constructors can't be async.
the solution is you should set constructor private, so no one can initialize the object. then add an static method which returns an instance of the object asynchronously.
here is an example in dart:
class FacetecPlugin {
final String _token;
// Ensures end-users cannot initialize the class.
FacetecPlugin._privateConstructor({required String token}) : _token = token;
Future<void> checkLiveness() async {
await FacetecPlatform.instance.checkLiveness(_token);
}
//This is method should be called before any usage of FacetecPlugin plugin.
static Future<FacetecPlugin> initialize(Configuration config) async {
final initialized = await FacetecPlatform.instance.initialize(
deviceKeyIdentifier: config.deviceKey,
publicEncryptionKey: config.publicEncryptionKey);
if (!initialized) {
throw Exception('Facetec SDK initialization failed.');
}
final token = await _getSessionToken(config);
// creating an instance of the plugin with token and returning it.
return FacetecPlugin._privateConstructor(token: token);
}
# other methods have been omitted for brevity.
Now user can't construct the plugin directly. but he has to use initialize method which return a properly constructed plugin and is ready to use.
// final facetecPlugin = FacetecPlugin() // can't be called. constructor is private
final facetecPlugin = await FacetecPlugin.initialize(Configuration(deviceId:'1234'));
final result = await facetecPlugin.checkLiveness()
I want to open a file in a class constructor. It is possible that the opening could fail, then the object construction could not be completed. How to handle this failure? Throw exception out? If this is possible, how to handle it in a non-throw constructor?
If an object construction fails, throw an exception.
The alternative is awful. You would have to create a flag if the construction succeeded, and check it in every method.
I want to open a file in a class constructor. It is possible that the opening could fail, then the object construction could not be completed. How to handle this failure? Throw exception out?
Yes.
If this is possible, how to handle it in a non-throw constructor?
Your options are:
redesign the app so it doesn't need constructors to be non-throwing - really, do it if possible
add a flag and test for successful construction
you could have each member function that might legitimately be called immediately after the constructor test the flag, ideally throwing if it's set, but otherwise returning an error code
This is ugly, and difficult to keep right if you have a volatile group of developers working on the code.
You can get some compile-time checking of this by having the object polymorphically defer to either of two implementations: a successfully constructed one and an always-error version, but that introduces heap usage and performance costs.
You can move the burden of checking the flag from the called code to the callee by documenting a requirement that they call some "is_valid()" or similar function before using the object: again error prone and ugly, but even more distributed, unenforcable and out of control.
You can make this a little easier and more localised for the caller if you support something like: if (X x) ... (i.e. the object can be evaluated in a boolean context, normally by providing operator bool() const or similar integral conversion), but then you don't have x in scope to query for details of the error. This may be familiar from e.g. if (std::ifstream f(filename)) { ... } else ...;
have the caller provide a stream they're responsible for having opened... (known as Dependency Injection or DI)... in some cases, this doesn't work that well:
you can still have errors when you go to use the stream inside your constructor, what then?
the file itself might be an implementation detail that should be private to your class rather than exposed to the caller: what if you want to remove that requirement later? For example: you might have been reading a lookup table of precalculated results from a file, but have made your calculations so fast there's no need to precalculate - it's painful (sometimes even impractical in an enterprise environment) to remove the file at every point of client usage, and forces a lot more recompilation rather than potentially simply relinking.
force the caller to provide a buffer to a success/failure/error-condition variable which the constructor sets: e.g. bool worked; X x(&worked); if (worked) ...
this burden and verbosity draws attention and hopefully makes the caller much more conscious of the need to consult the variable after constructing the object
force the caller to construct the object via some other function that can use return codes and/or exceptions:
if (X* p = x_factory()) ...
Smart_Ptr_Throws_On_Null_Deref p_x = x_factory();</li>
<li>X x; // never usable; if (init_x(&x)) ...`
etc...
In short, C++ is designed to provide elegant solutions to these sorts of issues: in this case exceptions. If you artificially restrict yourself from using them, then don't expect there to be something else that does half as good a job.
(P.S. I like passing variables that will be modified by pointer - as per worked above - I know the FAQ lite discourages it but disagree with the reasoning. Not particularly interested in discussion thereon unless you've something not covered by the FAQ.)
New C++ standard redefines this in so many ways that it's time to revisit this question.
Best choices:
Named optional: Have a minimal private constructor and a named constructor: static std::experimental::optional<T> construct(...). The latter tries to set up member fields, ensures invariant and only calls the private constructor if it'll surely succeed. Private constructor only populates member fields. It's easy to test the optional and it's inexpensive (even the copy can be spared in a good implementation).
Functional style: The good news is, (non-named) constructors are never virtual. Therefore, you can replace them with a static template member function that, apart from the constructor parameters, takes two (or more) lambdas: one if it was successful, one if it failed. The 'real' constructor is still private and cannot fail. This might sound an overkill, but lambdas are optimized wonderfully by compilers. You might even spare the if of the optional this way.
Good choices:
Exception: If all else fails, use an exception - but note that you can't catch an exception during static initialization. A possible workaround is to have a function's return value initialize the object in this case.
Builder class: If construction is complicated, have a class that does validation and possibly some preprocessing to the point that the operation cannot fail. Let it have a way to return status (yep, error function). I'd personally make it stack-only, so people won't pass it around; then let it have a .build() method that constructs the other class. If builder is friend, constructor can be private. It might even take something only builder can construct so that it's documented that this constructor is only to be called by builder.
Bad choices: (but seen many times)
Flag: Don't mess up your class invariant by having an 'invalid' state. This is exactly why we have optional<>. Think of optional<T> that can be invalid, T that can't. A (member or global) function that works only on valid objects works on T. One that surely returns valid works on T. One that might return an invalid object return optional<T>. One that might invalidate an object take non-const optional<T>& or optional<T>*. This way, you won't need to check in each and every function that your object is valid (and those ifs might become a bit expensive), but then don't fail at the constructor, either.
Default construct and setters: This is basically the same as Flag, only that this time you're forced to have a mutable pattern. Forget setters, they unnecessarily complicate your class invariant. Remember to keep your class simple, not construction simple.
Default construct and init() that takes a ctor parameters: This is nothing better than a function that returns an optional<>, but requires two constructions and messes up your invariant.
Take bool& succeed: This was what we were doing before optional<>. The reason optional<> is superior, you cannot mistakenly (or carelessly!) ignore the succeed flag and continue using the partially constructed object.
Factory that returns a pointer: This is less general as it forces the object to be dynamically allocated. Either you return a given type of managed pointer (and therefore restrict allocation/scoping schema) or return naked ptr and risk clients leaking. Also, with move schematics performance-wise this might become less desirable (locals, when kept on stack, are very fast and cache-friendly).
Example:
#include <iostream>
#include <experimental/optional>
#include <cmath>
class C
{
public:
friend std::ostream& operator<<(std::ostream& os, const C& c)
{
return os << c.m_d << " " << c.m_sqrtd;
}
static std::experimental::optional<C> construct(const double d)
{
if (d>=0)
return C(d, sqrt(d));
return std::experimental::nullopt;
}
template<typename Success, typename Failed>
static auto if_construct(const double d, Success success, Failed failed = []{})
{
return d>=0? success( C(d, sqrt(d)) ): failed();
}
/*C(const double d)
: m_d(d), m_sqrtd(d>=0? sqrt(d): throw std::logic_error("C: Negative d"))
{
}*/
private:
C(const double d, const double sqrtd)
: m_d(d), m_sqrtd(sqrtd)
{
}
double m_d;
double m_sqrtd;
};
int main()
{
const double d = 2.0; // -1.0
// method 1. Named optional
if (auto&& COpt = C::construct(d))
{
C& c = *COpt;
std::cout << c << std::endl;
}
else
{
std::cout << "Error in 1." << std::endl;
}
// method 2. Functional style
C::if_construct(d, [&](C c)
{
std::cout << c << std::endl;
},
[]
{
std::cout << "Error in 2." << std::endl;
});
}
My suggestion for this specific situation is that if you don't want a constuctor to fail because if can't open a file, then avoid that situation. Pass in an already open file to the constructor if that's what you want, then it can't fail...
One way is to throw an exception. Another is to have a 'bool is_open()' or 'bool is_valid()' functuon that returns false if something went wrong in the constructor.
Some comments here say it's wrong to open a file in the constructor. I'll point out that ifstream is part of the C++ standard it has the following constructor:
explicit ifstream ( const char * filename, ios_base::openmode mode = ios_base::in );
It doesn't throw an exception, but it has an is_open function:
bool is_open ( );
I want to open a file in a class constructor.
Almost certainly a bad idea. Very few cases when opening a file during construction is appropriate.
It is possible that the opening could fail, then the object construction could not be completed. How to handle this failure? Throw exception out?
Yep, that'd be the way.
If this is possible, how to handle it in a non-throw constructor?
Make it possible that a fully constructed object of your class can be invalid. This means providing validation routines, using them, etc...ick
A constructor may well open a file (not necessarily a bad idea) and may throw if the file-open fails, or if the input file does not contain compatible data.
It is reasonable behaviour for a constructor to throw an exception, however you will then be limited as to its use.
You will not be able to create static (compilation unit file-level) instances of this class that are constructed before "main()", as a constructor should only ever be thrown in the regular flow.
This can extend to later "first-time" lazy evaluation, where something is loaded the first time it is required, for example in a boost::once construct the call_once function should never throw.
You may use it in an IOC (Inversion of Control / Dependency Injection) environment. This is why IOC environments are advantageous.
Be certain that if your constructor throws then your destructor will not be called. So anything you initialised in the constructor prior to this point must be contained in an RAII object.
More dangerous by the way can be closing the file in the destructor if this flushes the write buffer. No way at all to handle any error that may occur at this point properly.
You can handle it without an exception by leaving the object in a "failed" state. This is the way you must do it in cases where throwing is not permitted, but of course your code must check for the error.
Use a factory.
A factory can be either an entire factory class "Factory<T>" for building your "T" objects (it doesn't have to be a template) or a static public method of "T". You then make the constructor protected and leave the destructor public. That ensures new classes can still derive from "T" but no external code other than them can call the constructor directly.
With factory methods (C++17)
class Foo {
protected:
Foo() noexcept; // Default ctor that can't fail
virtual bool Initialize(..); // Parts of ctor that CAN fail
public:
static std::optional<Foo> Create(...) // 'Stack' or value-semantics version (no 'new')
{
Foo out();
if(foo.Initialize(..)) return {out};
return {};
}
static Foo* /*OR smart ptr*/ Create(...) // Heap version.
{
Foo* out = new Foo();
if(foo->Initialize(...) return out;
delete out;
return nullptr;
}
virtual ~Foo() noexcept; // Keep public to allow normal inheritance
};
Unlike setting 'valid' bits or other hacks, this is relatively clean and extensible. Done right it guarantees no invalid objects ever escape into the wild, and writing derived 'Foo's is still straightforward. And since factory functions are normal functions, you can do a lot of other things with them that constructors can't.
In my humble opinion you should never put any code that can realistically fail into a constructor. That pretty much means anything that does I/O or other 'real work'. Constructors are a special corner case of the language, and they basically lack the ability to do error handling.
I'm currently working on a C++ project, where dynamic arrays often appear.
I was wondering, what could be the correct way to initialize a dynamic array using the new-operator? A colleague of mine told me that it's a no-no to use new within the constructor, since a constructor is a construct that shouldn't be prone to errors or shouldn't fail at all, respectively. Now let's consider the following example: We have two classes, a more or less complex class State and a class StateContainer, which should be self-explained.
class State {
private:
unsigned smth;
public:
State();
State( unsigned s );
};
class StateContainer {
private:
unsigned long nStates;
State *states;
public:
StateContainer();
StateContainer( unsigned long n );
virtual ~StateContainer();
};
StateContainer::StateContainer() {
nStates = SOME_DEFINE_N_STATES;
states = new State[nStates];
if ( !states ) {
// Error handling
}
}
StateContainer::StateContainer( unsigned long n ) {
nStates = n;
try {
states = new State[nStates]
} catch ( std::bad_alloc &e ) {
// Error handling
}
}
StateContainer::~StateContainer() {
if ( states ) {
delete[] states;
states = 0;
}
}
Now actually, I have two questions:
1.) Is it ok, to call new within a constructor, or is it better to create an extra init()-Method for the State-Array and why?
2.) Whats the best way to check if new succeeded:
if (!ptr) std::cerr << "new failed."
or
try { /*new*/ } catch (std::bad_alloc) { /*handling*/ }
3.) Ok its three questions ;o) Under the hood, new does some sort of
ptr = (Struct *)malloc(N*sizeof(Struct));
And then call the constructor, right?
You should let the std::bad_alloc propagate - there's likely nothing reasonable you could do anyway.
First of all, throwing an exception from the constructor is the only reliable way to signal a problem - if there's no exception it means the object is completely constructed. So catching std::bad_alloc alone will not help against other possible exceptions.
Then what can you do to "handle" it in such a way that the other code is aware and can react appropriately?
Use exceptions right - let them propagate to the site where they can be reasonably handled.
The entire purpose of a constructor is to construct an object. That includes initialization. When the constructor finishes executing, the object should be ready to use. That means the constructor should perform any initialization that is necessary.
What your friend suggests leads to unmaintainable and error-prone code, and goes against every good C++ practice. He is wrong.
As for your dynamic arrays, use std::vector instead. And to initialize it, simply pass a parameter to the constructor:
std::vector<int>(10, 20)
will create a vector of 10 integers, all of them initialized to the value 20.
Not a complete answer, just my 2 cents:
1: I would use new in the constructor, although for dynamic arrays, STL is the way to go.
2: the normal error-handling for new is to raise an exception, so checking the returned pointer is useless.
3: don't forget the new-operator to make the story a little bit more interesting.
Short answer:
No, your friend is wrong. The constructor is where you do allocation + initialization. We even have a term called "Resource Acquisition is Initialization" (RAII)... classes acquire resources as part of their initialization in the constructor and classes free those acquired resources in their destructors.
Long answer:
Consider the following code in a constructor:
member1 = new whatever1[n];
member2 = new whatever2[m];
Now, suppose in the above that the second allocation were to throw an exception, either because the construction of whatever2 failed and threw an exception, or the allocation failed and threw std::bad_alloc. The result is that the memory that you've allocated for whatever1 will have been leaked.
For this reason, it is better to use a container class such as std::vector:
MyClass::MyClass(std::size_t n, std::size_t m) : member1(n), member2(m) {}
// where member1 and member2 are of type std::vector
When using type std::vector, if the second allocation fails, the destructor of the previous std::vector will be invoked, causing the resources to be appropriately released. This is probably what your friend meant when he said you shouldn't be using new (you should be using a container class, instead), in which case he would be mostly correct... although there are smart pointer classes such as boost::shared_ptr which provide you with these same safety guarantees and where you would still need to use new, so he still isn't quite right.
Note that if you have only one object/array that you are allocating, then this is not an issue... which is the way things are in your code... you don't have to worry about leaks due to some other allocation failing. Also, I should add that new will either succeed or throw an exception; it will not return NULL, and so that check is pointless. The only instance where you should catch std::bad_alloc is in the case where you have been forced to do several allocations (you are forbidden from using std::vector), in which case you deallocate the other resources in the handler, but then you rethrow the exception, because you should let it propagate.
Your friend is somewhat right. However, it is common practice to do memory reservations in the Constructor, and deallocations in the Destructor.
The problem with methods that may fail in Constructors is as follows: The constructor has no traditional means of notifying the caller of the problem. The caller expects to get an object instance that is not corrupt in any way.
The solution to this problem is to throw/propagate an exception. The exception will always get through and can be handled by the caller.
If you are looking out for a return type i.e. if the function has to return a status then use the separate function (init()) to allocate memory.
If you check are going to check whether the memory got allocated by checking the NULL condition in all the member functions then allocate memory in the constructor itself.
The exception handling (i.e. try...catch) is a better choice.
Apart from calling the constructor the "this" pointer is also initialized.
I have a case in which I have to read an input file in the C'tor, but sometimes this file doesn't exist.
This object is usually held statically, so its C'tor is called while loading the dll.
I can't catch the exception I throw if the file doesn't exist because it's too early, and my executable crashes in an ugly way.
I know it's bad practice to throw exceptions out of a C'tor, but I can't go on if the file doesn't exist, so I have to.
Is there a way to catch the exception while loading the dll, and if not, is there any better solution for this scenario?
Thanks,
Gal
I assume the static object has the file scope (it is outside any function/class definition). You may consider moving it to an accessor function and accessing it only via that function, like this:
class Object;
Object& getObject()
{
static Object object;
return object;
}
The static instance of Object will be initialized upon the first calling of the getObject() method. If the Object's constructor throws, you can easily catch the exception. Just you need to remember wrapping every call of getObject() into a try/catch block (or suffer from the exception bubbling up the stack chain); that may be a bit inconvenient, but on the other hand you may decide to wrap just the logically "first" call, if you know which one it is in the program logic flow.
Throwing exceptions out of a constructor is not necessarily a bad practice. In fact, RAII usually requires you to do this sort of things, because objects have an internal invariant that must be satisfied, and if the constructor can't initialize the object and leave it in a valid state, then it's the only way to go.
Throwing exceptions from a destructor, on the other hand, is a bad practice (and also a dangerous one). But throwing them from a constructor should be OK.
If you can use c++11 then there is a lambda and unique_ptr<> solution to this:
// In some_file.hpp
#pragma once
#include <memory>
#include <stdexcept>
class CtorThrows {
public:
CtorThrows (int value) {
if (value < 10) {
throw std::runtime_error("oops!");
}
}
};
class ClassWithStatic {
public:
private:
static std::unique_ptr<CtorThrows> bad_member_; // <-- static member
};
and then
// In some_file.cpp
#include "some_file.hpp"
// Create a lambda function to initialize the static member variable.
std::unique_ptr<CtorThrows> ClassWithStatic::bad_member_ = []() {
try {
int value = 5; // in this case, it is a bad value
// This only returns successfully if bad_value DOESN'T cause
// the ctor to throw and exception.
return std::make_unique<CtorThrows>(value);
} catch (std::runtime_error &e) {
std::cerr << "OOPs! Here's a nice error message" << std::endl;
exit(1);
}
return std::unique_ptr<CtorThrows>(nullptr);
}();
Using a unique_ptr lets you do this even with classes with that have a deleted or private copy constructor and copy assignment operator.
Redesign the object in such a way that it opens the file later - for example when the data from the file is requested the first time.
Alternatively replase the static object with a static pointer and call new when needed. It's better to use a smart pointer like auto_ptr.
How about separating reading the input file from the Constructor? You could have a separate Init() Method that must be called after constructing the object but before the object is actually ready to use.
You're right that you can't catch exeptions that happen during the initialization of static objects.
Since you're writing a DLL: Each DLL can have an entry-point, and inside this entry point exception handling works. (It's the same as main in your main-program). I'd remove the static instances of your classes, replace them with pointers and initialize these pointers inside dllmain.
That'll solve your problems once for all.
Btw - the DLL entrypoint gets called on load, unload and other events such as process attach/detach ect. Be sure you use the correct place to initialize your classes.
One way may be to "design" this to make the calling code (i.e. the code outside the dll) responsible for making sure all dependencies of the dll is in place. A function in the calling code that makes sure the dll's dependencies, in this case the file, is in place and is loadable before loading the library. If not, it can gracefully exit.