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.
Related
I read the following
The inability to gracefully handle errors in C++ constructors is one
good reason to avoid constructors that do more than nothing, and use
initialization functions instead. And C++ exceptions are not a
graceful way to handle errors, especially in constructors. If your
member object constructor throws an exception, and you want to catch
it in your constructor, the normally ugly colon syntax gets much
uglier.
I would like to know why constructors can't gracefully handle errors ? Constructors can still support try-catch so why is it that constructors can't gracefully handle errors ?
I would like to know why constructors cant gracefully handle errors ?
They can, by throwing an exception if initialisation fails.
This is far more "graceful" than the suggestion to leave the object in a half-alive state, to be properly initialised by calling a function later. Used correctly[1], exceptions guarantee that the object is either fully initialised, or doesn't exist.
This advice presumably comes from someone who disapproves of the use of exceptions to report error conditions; in which case C++ does indeed become an extremely clumsy language, with no convenient way to express initialisation failure. Fortunately, the use of exceptions is idiomatic among most C++ programmers, so there's usually no need to pay attention to this kind of nonsense.
[1] Specifically, in conjunction with RAII, to avoid the need to "catch it in your constructor" or anywhere apart from the error handler itself.
I think "gracefully handling errors" is subjective...
Anyway, probably the author is thinking of something like:
class X
{
private:
int * v1; // a vector of int's, dynamically allocated
int * v2; // another vector of int's, dynamically allocated
public:
X()
{
v1 = new int[...];
.... do something
v2 = new int[...];
... If this throws, then v1 is leaked, since destructor is not called for X
...
}
};
Actually, I think that if you proper use RAII and RAII building-blocks, there are no problems, and constructor can handle errors gracefully (for some meaning of "gracefully").
In the above example, if you replace the raw dynamically-allocated arrays with a RAII building-block like std::vector, you have no problems, since destructors are called on data members if an exception is thrown in the constructor of class X (even if the destructor for X is not called):
class X
{
private:
std::vector<int> v1;
std::vector<int> v2;
public:
X()
{
v1.resize(...);
.... do something
v2.resize(...);
// If this throws, then v1 is NOT leaked,
// since the destructor is called for v1 data member
...
}
};
Anyway, there are cases in which you just don't want the constructor to throw, e.g. a file class, in which you can have an IsOpen() member function to check if the file was opened successfully in the constructor (instead of having the constructor throwing an exception if file open fails).
This is just a matter of personal design preference.
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 refreshing my C++ knowledge after not having used it in anger for a number of years. In writing some code to implement some data structure for practice, I wanted to make sure that my code was exception safe. So I've tried to use std::auto_ptrs in what I think is an appropriate way. Simplifying somewhat, this is what I have:
class Tree
{
public:
~Tree() { /* delete all Node*s in the tree */ }
void insert(const string& to_insert);
...
private:
struct Node {
...
vector<Node*> m_children;
};
Node* m_root;
};
template<T>
void push_back(vector<T*>& v, auto_ptr<T> x)
{
v.push_back(x.get());
x.release();
}
void Tree::insert(const string& to_insert)
{
Node* n = ...; // find where to insert the new node
...
push_back(n->m_children, auto_ptr<Node>(new Node(to_insert));
...
}
So I'm wrapping the function that would put the pointer into the container, vector::push_back, and relying on the by-value auto_ptr argument to
ensure that the Node* is deleted if the vector resize fails.
Is this an idiomatic use of auto_ptr to save a bit of boilerplate in my
Tree::insert? Any improvements you can suggest? Otherwise I'd have to have
something like:
Node* n = ...; // find where to insert the new node
auto_ptr<Node> new_node(new Node(to_insert));
n->m_children.push_back(new_node.get());
new_node.release();
which kind of clutters up what would have been a single line of code if I wasn't
worrying about exception safety and a memory leak.
(Actually I was wondering if I could post my whole code sample (about 300 lines) and ask people to critique it for idiomatic C++ usage in general, but I'm not sure whether that kind of question is appropriate on stackoverflow.)
It is not idiomatic to write your own container: it is rather exceptional, and for the most part useful only for learning how to write containers. At any rate, it is most certainly not idiomatic to use std::autp_ptr with standard containers. In fact, it's wrong, because copies of std::auto_ptr aren't equivalent: only one auto_ptr owns a pointee at any given time.
As for idiomatic use of std::auto_ptr, you should always name your auto_ptr on construction:
int wtv() { /* ... */ }
void trp(std::auto_ptr<int> p, int i) { /* ... */ }
void safe() {
std::auto_ptr<int> p(new int(12));
trp(p, wtv());
}
void danger() {
trp(std::auto_ptr<int>(new int(12)), wtv());
}
Because the C++ standard allows arguments to evaluate in any arbitrary order, the call to danger() is unsafe. In the call to trp() in danger(), the compiler may allocate the integer, then create the auto_ptr, and finally call wtv(). Or, the compiler may allocate a new integer, call wtv(), and finally create the auto_ptr. If wtv() throws an exception then danger() may or may not leak.
In the case of safe(), however, because the auto_ptr is constructed a-priori, RAII guarantees it will clean up properly whether or not wtv() throws an exception.
Yes it is.
For example, see the interface of the Boost.Pointer Container library. The various pointer containers all feature an insert function taking an auto_ptr which semantically guarantees that they take ownership (they also have the raw pointer version but hey :p).
There are however other ways to achieve what you're doing with regards to exception safety because it's only internal here. To understand it, you need to understand what could go wrong (ie throw) and then reorder your instructions so that the operations that may throw are done with before the side-effects occur.
For example, taking from your post:
auto_ptr<Node> new_node(new Node(to_insert)); // 1
n->m_children.push_back(new_node.get()); // 2
new_node.release(); // 3
Let's check each line,
The constructor may throw (for example if the CopyConstructor of the type throws), in this case however you are guaranteed that new will perform the cleanup for you
The call to push_back may throw a std::bad_alloc if the memory is exhausted. That's the only error possible as copying a pointer is a no-throw operation
This is guaranteed not to throw
If you look closely, you'll remark that you would not have to worry if you could somehow have 2 being executed before 1. It is in fact possible:
n->m_children.reserve(n->m_children.size() + 1);
n->m_children.push_back(new Node(to_insert));
The call to reserve may throw (bad_alloc), but if it completes normally you are then guaranteed that no reallocation will occur until size becomes equal to capacity and you try another insertion.
The call to new may fall if the constructor throw, in which case new will perform the cleanup, if it completes you're left with a pointer that is immediately inserted in the vector... which is guaranteed not to throw because of the line above.
Thus, the use of auto_ptr may be replaced here. It was nonetheless a good idea, though as has been noted you should refrain from executing RAII initialization within a function evaluation.
I like the idea of declaring the ownership of pointer. This is one of the great features in c++0x, std::unique_ptrs. However std::auto_ptr is so hard to understand and lethal is even slightly misued I would suggest avoiding it entirely.
http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
Yesterday I read some code of a colleague and came across this:
class a_class
{
public:
a_class() {...}
int some_method(int some_param) {...}
int value_1;
int value_2;
float value_3;
std::vector<some_other_class*> even_more_values;
/* and so on */
}
a_class a_instances[10];
void some_function()
{
do_stuff();
do_more_stuff();
memset(a_instances, 0, 10 * sizeof(a_class)); // <===== WTF?
}
Is that legal (the WTF line, not the public attributes)? To me it smells really, really bad...
The code ran fine when compiled with VC8, but it throws an "unexpected exception" when compiled with VC9 when calling a_instances[0].event_more_values.push_back(whatever), but when accessing any of the other members. Any insights?
EDIT: Changed the memset from memset(&a_instances... to memset(a_instances.... Thanks for pointing it out Eduard.
EDIT2: Removed the ctor's return type. Thanks litb.
Conclusion: Thanks folks, you confirmed my suspicion.
This is a widely accepted method for initialization for C structs.
In C++ it doesn't work ofcourse because you can't assume anything about vectors internal structure. Zeroing it out is very likely to leave it in an illegal state which is why your program crashes.
He uses memset on a non-POD class type. It's invalid, because C++ only allows it for the simplest cases: Where a class doesn't have a user declared constructor, destructor, no virtual functions and several more restrictions. An array of objects of it won't change that fact.
If he removes the vector he is fine with using memset on it though. One note though. Even if it isn't C++, it might still be valid for his compiler - because if the Standard says something has undefined behavior, implementations can do everything they want - including blessing such behavior and saying what happens. In his case, what happens is probably that you apply memset on it, and it would silently clear out any members of the vector. Possible pointers in it, that would point to the allocated memory, will now just contain zero, without it knowing that.
You can recommend him to clear it out using something like this:
...
for(size_t i=0; i < 10; i++)
objects[i].clear();
And write clear using something like:
void clear() {
a_object o;
o.swap(*this);
}
Swapping would just swap the vector of o with the one of *this, and clear out the other variables. Swapping a vector is especially cheap. He of course needs to write a swap function then, that swaps the vector (even_more_values.swap(that.even_more_values)) and the other variables.
I am not sure, but I think the memset would erase internal data of the vector.
When zeroing out a_instances, you also zero out the std_vector within. Which probably allocates a buffer when constructed. Now, when you try to push_back, it sees the pointer to the buffer being NULL (or some other internal member) so it throws an exception.
It's not legitimate if you ask. That's because you can't overload writing via pointers as you can overload assignment operators.
The worst part of it is that if the vector had anything in it, that memory is now lost because the constructor wasn't called.
NEVER over-write a C++ object. EVER. If it was a derived object (and I don't know the specifics of std::vector), this code also over-writes the object's vtable making it crashy as well as corrupted.
Whoever wrote this doesn't understand what objects are and needs you to explain what they are and how they work so that they don't make this kind of mistake in the future.
You shouldn't do memset on C++ objects, because it doesn't call the proper constructor or destructor.
Specifically in this case, the destructor of even_more_values member of all a_instances's elements is not called.
Actually, at least with the members that you listed (before /* and so on */), you don't need to call memset or create any special destructor or clear() function. All these members are deleted automatically by the default destructor.
You should implement a method 'clear' in your class
void clear()
{
value1=0;
value2=0;
value_3=0f;
even_more_values.clear();
}
What you have here might not crash, but it probably won't do what you want either! Zeroing out the vector won't call the destructor for each a_class instance. It will also overwrite the internal data for a_class.even_more_values (so if your push_back() is after the memset() you are likely to get an access violation).
I would do two things differently:
Use std::vector for your storage both in a_class and in some_function().
Write a destructor for a_class that cleans up properly
If you do this, the storage will be managed for you by the compiler automatically.
For instance:
class a_class
{
public:
a_class() {...}
~a_class() { /* make sure that even_more_values gets cleaned up properly */ }
int some_method(int some_param) {...}
int value_1;
int value_2;
float value_3;
std::vector<some_other_class*> even_more_values;
/* and so on */
}
void some_function()
{
std::vector<a_class> a_instances( 10 );
// Pass a_instances into these functions by reference rather than by using
// a global. This is re-entrant and more likely to be thread-safe.
do_stuff( a_instances );
do_more_stuff( a_instances );
// a_instances will be cleaned up automatically here. This also allows you some
// weak exception safety.
}
Remember that if even_more_values contains pointers to other objects, you will need to delete those objects in the destructor of a_class. If possible, even_more_values should contain the objects themselves rather than pointers to those objects (that way you may not have to write a destructor for a_class, the one the compiler provides for you may be sufficient).