How to allocate an object with a complex constructor? - c++

I think I know C++ reasonably well and I am thinking about implementing something a bit bigger than a "toy" program. I know the difference between stack- and heap-memory and the RAII-idiom.
Lets assume I have a simple class point:
class point {
public:
int x;
int y;
point(int x, int y) : x(x), y(y) {}
};
I would allocate points always on the stack, since the objects are small. Since on 64-bit machines sizeof(point) == sizeof(void*), if a am not wrong, I would go even further and pass points by value by default.
Now lets assume a more complex class battlefield, that I want to use in the class game:
class battlefield {
public:
battlefield(int w, int h, int start_x, int start_y, istream &in) {
// Complex generation of a battlefield from a file/network stream/whatever.
}
};
Since I really like RAII and the automatic cleanup when an object leaves the scope I am tempted to allocate the battlefield on the stack.
game::game(const settings &s) :
battlefield(s.read("w"), s.read("h"), gen_random_int(), gen_random_int(), gen_istream(s.read("level_number"))) {
// ...
}
But I have several problems now:
Since this class has not got a zero-args-constructor I have to initialize it in the initialisation list of the class I use battlefield in. This is cumbersome since I need a istream from somewhere. This leads to the next problem.
The complex constructors "snowball" at some point. When I use battlefield in the game class and initialize it in the initialisation list the constructor of game, the constructor of game will become fairly complex too and the initialisation of game itself might become cumbersome too. (When I decide to take the istream as argument of the game constructor)
I need auxiliary functions to fill in complex parameters.
I see two solutions to this problem:
Either I create a simple constructor for battlefield that does not initialize the object. But this approach has the problem that I have a half-initialized object, aka an object that violates the RAII-idiom. Strange things might happen when calling methods on such an object.
game::game(const settings &s) {
random_gen r;
int x = r.random_int();
int y = r.random_int();
ifstream in(s.read("level_number"));
in.open();
this->battlefield.init(s.read("w"), s.read("h"), x, y, in);
// ...
}
Or I allocate battlefield on the heap in the game constructor. But I have to beware of exceptions in the constructor and I have to take care that the destructor deletes the battlefield.
game::game(const settings &s) {
random_gen r;
int x = r.random_int();
int y = r.random_int();
ifstream in(s.read("level_number"));
in.open();
this->battlefield = new battlefield(s.read("w"), s.read("h"), x, y, in);
// ...
}
I hope you can see the problem I am thinking of. Some questions that arise for me are:
Is there a design pattern for this situations I do not know?
What is the best practise in bigger C++ projects? Which objects are allocated on the heap, which ones are allocated on the stack? Why?
What is the general advice regarding the complexity of constructors? Is reading from a file too much for a constructor? (Since this problem mostly arises from the complex constructor.)

You could let your battlefield be constructed from settings:
explicit battlefield(const settings& s);
or alternatively, why not create a factory function for your battlefield?
E.g.
battlefield CreateBattlefield(const settings& s)
{
int w = s.read("w");
int h = s.read("w");
std::istream& in = s.genistream();
return battlefield(w, h, gen_random_int(), gen_random_int(), in);
}
game::game(const settings &s) :
battlefield(CreateBattlefield(s)) {
// ...
}

But this approach has the problem that I have a half-initialized object, aka an object that violates the RAII-idiom.
That is not RAII. The concept is you use objects to manage the resources. When you aquire a resource like heap memory, semaphore, file handle, you have to transfer the ownership to a resource managing class. This is what smart pointers in C++ are meant for. You have to use either unique_ptr if you want to have sole ownership of the object or use a shared_ptr if you want multiple pointers to have ownership.
Or I allocate battlefield on the heap in the game constructor. But I have to beware of exceptions in the constructor and I have to take care that the destructor deletes the battlefield.
If your constructor throws an exception, then the destructor of the object would not be called and you might end up in a half-cooked object. In this case, you have to remember what allocations you did in the constructor before the exception was thrown and deallocate all those. Again smart pointers will help automatic cleaning of resources. See this faq
Which objects are allocated on the heap, which ones are allocated on the stack? Why?
Try to allocate the objects in stack whenever possible. Your objects then have life only in the scope of that block. If you have a case where this is not possible go for heap allocation - eg: you only know the size at runtime, the size of the object is too big to sit on stack.

Related

Why do I have to use pointers if I define a constructor?

When I create a constructor for my class, C++ forces me to do two things:
Define rect as a pointer as I am using the new keyword.
As I defined it as a pointer I need to use the -> instead of the . to access their properties, methods.
My question is, why is it like that? I come from a Java background and it's not like that in Java, so I guess there is an advantage here I am not able to see. Can someone clarify this for me? And my apologies for the newbie question.
With constructor
// classes example
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
void set_values (int,int);
int area() {return width*height;}
Rectangle(int w,int h) {
width = w;
height = h;
}
};
int main () {
Rectangle* rect = new Rectangle(5,8);
cout << "area: " << rect -> area();
return 0;
}
No constructor
// classes example
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
void set_values (int,int);
int area() {return width*height;}
};
void Rectangle::set_values (int x, int y) {
width = x;
height = y;
}
int main () {
Rectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
return 0;
}
On the notation used to access class members, there are some similarities between C++ and Java:
The a->b of C++ is normally equivalent to (*a).b. I say normally since it is possible in C++ to overload the pointer to member operator ->, whereas it's not possible to overload . (Although there is some movement in the C++ Standards Committee to relax that.)
As for the creation of instances of classes, complexities arise in C++ as, unlike Java, you have essentially two choices concerning class (and plain old data) type instantiation. You can use
Automatic storage duration: Rectangle rect(1, 2);
Dynamic storage duration: Rectangle* rect = new Rectangle(1, 2);
(A couple of other choices - static and thread_local have more of the first flavour.)
Note that in C++, unlike Java, you need to call delete to free the memory associated with the pointer that's been given to you by new. Some classes in C++ (e.g. std::unique_ptr) help a lot in managing that memory.
You don't have to use pointers just because you have a constructor in your class. The two things are unrelated.
Your example of
Rectangle* rect = new Rectangle(5,8);
can easily be rewritten without pointers:
Rectangle rect(5,8);
Also note that Rectangle rect; still invokes a constructor: The default constructor (taking no arguments), Rectangle::Rectangle(). The compiler will generate a default constructor for you if you don't define a constructor yourself.
The major difference (that's important here, anyway) between Java and C++ is memory management.
To a first approximation, in Java everything is an object allocated on the heap, and you access those objects via references (although they're more like C++ pointers than C++ references, and sometimes you may well see them called pointers). The exception is primitive types like int, which is why you can't create an ArrayList<int>. The system manages the lifetimes of objects for you using garbage collection; when nothing holds a reference to an object, it's collected.
C++ offers you more choice. One option is that you can allocate objects on the heap and access those objects via pointers, using the new keyword. So far, this is exactly the same as Java, which is probably why Java borrowed the use of the new keyword. The main difference here is that C++ doesn't keep track of the lifetime of those objects; you have to manually use the delete keyword when you want the object to be destroyed.
Alternatively, you can allocate on the stack, like so:
int main () {
Rectangle rect(5,8);
cout << "area: " << rect.area();
return 0;
}
Note that this does use the constructor! In this case, the memory for that rect object isn't on the heap, it's on the stack. In some ways, it's now more like a primitive type like int; it lives only as long as it's in scope. Some people will use the term "value semantics" to describe things like this. When it drops out of scope, the object is destroyed.
There are some advantages and disadvantages of using the stack compared to the heap. One is that it's a lot faster to allocate memory on the stack than on the heap (allocating memory on the stack is pretty much done by incrementing a single pointer!); another is that the lifetime of a stack object is completely obvious. A disadvantage is that the stack has a relatively small amount of memory available; if you try to allocate too much on the stack, you're at risk of er... overflowing your stack.
One key thing to flag up here that's different in C++ to Java is that in Java, when an object is destroyed is determined by the garbage collector. From the point of view of a program, it's non-deterministic. This isn't the case with C++; objects are destroyed either when they drop out of scope (for stack-allocated objects) or when they're explicitly deleted (for objects on the heap). So this is why it makes sense for C++ to have destructors, because you know when they'll get called.
This is why C++ doesn't have anything like Java's try-with-resources/AutoCloseable (or, for that matter, IDisposable in C#); the destructor takes that role. If, for example, you use a std::ifstream to read from file, and you create that object on the stack, the file will be closed for you when the ifstream drops out of scope, and this holds true for any sort of scope; you don't need a special syntax like try-with-resources.
Now, the typical practice in C++ is to use things allocated on the stack (with value semantics) to provide abstractions to help you do memory management. Examples of this include std::vector<> and std::unique_ptr<>. The pattern of using objects with C++ value semantics to manage the lifetime of other resources (like memory, open files, locks on a mutex, etc.) is known as RAII.
So, to boil it down, the difference is that C++ has two different ways of allocating objects that have really different semantics (value/stack and reference/heap). Java (mostly) only has one (reference/heap). And despite them both having a . operator, the Java . operator behaves like the C++ -> operator, in that they access the fields of an object elsewhere via a pointer (C++) or reference (Java). They can actually both blow up in a similar way, if you try to use -> on a null pointer, or . on a null Java reference.
The C++ . operator accesses the fields of values. It does a different thing, which is why it's different.

C++: Optimizing out destructor call

There is a little code example here:
struct Data {
};
struct Init {
Data *m_data;
Init() : m_data(new Data) { }
~Init() {
delete m_data;
}
};
class Object {
private:
int m_initType;
Data *m_data;
public:
Object(const Init &init) : m_initType(0), m_data(init.m_data) { }
Object(Init &&init) : m_initType(1), m_data(init.m_data) { init.m_data = nullptr; }
~Object() {
if (m_initType==1) {
delete m_data;
}
}
};
Object can be initialized two ways:
const Init &: this initialization just stores m_data as a pointer, m_data is not owned, so ~Object() doesn't have to do anything (in this case, m_data will be destroyed at ~Init())
Init &&: this initialization transfers ownership of m_data, Object becomes the owner of m_data, so ~Object() needs to destroy it
Now, there is a function:
void somefunction(Object object);
This function is called in callInitA and callInitB:
void callInitA() {
Init x;
somefunction(x); // calls the "const Init &" constructor
}
void callInitB() {
somefunction(Init()); // calls the "Init &&" constructor
}
Now, here's what I'd like to accomplish: in the callInitA case, I'd like to make the compiler to optimize away the destructor call of the resulting temporary Object (Object is used frequently, and I'd like to decrease code size).
However, the compiler doesn't optimize it away (tested with GCC and clang).
Object is designed so it doesn't have any functions which alter m_initType, so the compiler would be able to find out that if m_initType is set to 0 at construct time, then it won't change, so at the destructor it is still be 0 -> no need to call destructor at all, as it would do nothing.
Even, m_initType is an unnecessary member of Object: it is only needed at destruct time.
Do you have any design ideas how to accomplish this?
UPDATE: I mean that using some kind of c++ construct (helper class, etc.). C++ is a powerful language, maybe with some kind of c++ trickery this can be done.
(My original problem is more complex that this simplified one: Object can be initialized with other kind of Init structures, but all Objects constructors boils down to getting a "Data*" somehow)
void callInitA() {
Init x;
somefunction(x); // calls the "const Init &" constructor
}
The destruction of x cannot be optimized away, regardless of the contents of Init. Doing so would violate the design of the language.
It's not just a matter of whether Init contains resources or not. Init x, like all objects, will allocate space on the stack that later needs to be cleaned up, as an implicit (not part of code that you yourself write) part of the destructor. It's impossible to avoid.
If the intention is for x to be an object that somefunction can call without having to repeatedly create and delete references to x, you should be handling it like this:
void callInitA(Init & x) { //Or Init const& x
somefunction(x); // calls the "const Init &" constructor
}
A few other notes:
Make sure you implement the Rule of Five (sometimes known as Rule of Three) on any object that owns resources.
You might consider wrapping all pointers inside std::unique_ptr, as it doesn't seem like you need functionality beyond what std::unique_ptr offers.
Your m_initType actually distinguishes between two kinds of Objects - those which own their memory and those which don't. Also, you mention that actually there are many kinds of Objects which can be initialized with all sorts of inputs; so actually there are all sorts of Objects. That would suggest Object should better be some abstract base class. Now, that wouldn't speed anything up or avoid destructor calls, but it might make your design more reasonable. Or maybe Object could be an std::variant (new in C++17, you can read up on it).
But then, you say that temporary Objects are "used frequently". So perhaps you should go another way: In your example, suppose you had
template <bool Owning> class Object;
which you would then specialize for the non-owning case, with only a const Init& constructor and default destruction, and the owning case, with only an Init&& constructor (considering the two you mentioned) and a destructor which deletes. This would mean templatizing the code that uses Object, which many mean larger code size, as well as having to know what kind of Objects you pass in; but if would avoid the condition check if that really bugs you so much.
I'd like to decrease code size
I kind of doubt that you do. Are you writing code for an embedded system? In that case it's kind of strange you use lots of temporary Objects which are sort-of polymorphic.

Remember the original object which is merely able to manage shared memory

I have a question about good C++ style:
I would like to write a class "MyClass" which has one or some pointers as members and MyClass is able to allocate memory to this pointers. I would like to use the implicit give default-copy-constructor (as well as the default-assignement-operator) to copy an instance of MyClass, so that only the pointers were copied and the new object share the data which the initial object has allocated.
My idea was to prohibit copied objects (created with copy constructor or assignment operator) to release memory (as well as allocate memory to member pointers). In order to distinguesh between copied objects and original objects (created by the constructor), I want to use the following code:
class MyClass
{
public:
MyClass(): originalPtr(this) { data = new char[100000]; }
~MyClass() { if(originalPtr == this) delete[] data; }
private:
MyClass *originalPtr;
char *data; // shared data (not copiable)
char otherFeatures[10]; // individual data (copiable)
};
Would this solution (using the comparison with the this-pointer) a good style for such a purpose (e.g. parsing an object by call by value) or is it risky? Of course, I assume that the original object live always longer than the copied objects.
Thank you!
No, this is a bad idea. If the pointers are shared by several instances, than the one to deallocate should be the last one to die, not the original one. This differs in the sense that the original one might not be the one to die, which would cause all others to be pointing at garbage. Even though you assume that it's the last one to die, you need to realise that the inner workings of a class should not rely on external assumptions. That is, the class has no guarantees on how its life span is managed by the rest of the implementation, so it shouldn't make assumptions.
In this situation you should track references to your data. The basic idea is to keep track of how many copies of the class you have. As soon as that count reaches zero, you are free to release that memory; the last copy has just died. Fortunately for you, STL already provides such an implementation. These are known as Smart Pointers. There are others, such as std::unique_ptr, which makes the opposite by ensuring that the data is owned only by a single instance.
Ok, assuming the general case, where the original object does not die at last. I like the idea to just count the instances. For example one could use such a concept:
class MyClass
{
public:
MyClass(): countOfInstances(new int())
{
++*countOfInstances;
data = new char[100000];
}
~MyClass()
{
--*countOfInstances;
if(!countOfInstances)
{
delete[] data;
delete countOfInstances;
}
}
MyClass(const MyClass &other) // analogous for the assignment operator
{
countOfInstances = other.countOfInstances;
data = other.data;
otherFeatures = other.otherFeatures;
++*countOfInstances;
}
private:
int *countOfInstances;
char *data; // shared data (not copiable)
char otherFeatures; // individual data (copiable)
};
Here, one should also make sure that the shared memory is completely allocated before allowing to make copies.

Allocating memory without initializing it in C++

I'm getting acquainted with C++, and I'm having a problem with memory management. In C, whenever I'd want to reserve memory for any number of elements, regardless of type, I would just call malloc() and then initialize by hand (through a loop), to whichever value I wanted. With C++'s new, everything is automagically initialized.
Problem is, I've got a BattlePoint class which goes a little something like this:
class BattlePoint {
public:
BattlePoint(int x, int y) : x(x), y(y) { };
bool operator==(const BattlePoint &right);
virtual ~BattlePoint();
private:
int x, y;
};
As you can see, it takes a few x and y values through the initializer and then sets its own x and y from it. The problem is, this function will be called from a function which will allocate an array of them:
BattleShip::BattleShip(BattlePoint start, enum shipTypeSize size, enum shipOrientation orientation) : size(size), orientation(orientation) {
points = new BattlePoint[size]; // Here be doubts.
}
So, I need my BattleShip's point to hold an array of BattlePoints, each one with different initialization values (such as 0,1; 0,2; 0,3, etcetera).
Question is: how could I allocate my memory uninitialized?
Julian,
P.S.: I haven't done any testing regarding the way new works, I simple read Wikipedia's article on it which says:
In the C++ programming language, as well as in many C++-based
languages, new is a language construct that dynamically allocates
memory on the heap and initialises the memory using the
constructor. Except for a form called the "placement new", new
attempts to allocate enough memory on the heap for the new data. If
successful, it initialises the memory and returns the address to the
newly allocated and initialised memory. However if new cannot allocate
memory on the heap it will throw an exception of type std::bad_alloc.
This removes the need to explicitly check the result of an allocation.
A call to delete, which calls the destructor and returns the memory
allocated by new back to the heap, must be made for every call to new
to avoid a memory leak.
placement new should be the solution, yet it makes no mention on how to do it.
P.S. 2: I know this can be done through stdlib's vector class, but I'm avoiding it on purpose.
You need to use a std::vector. In this case you can push_back whatever you want, e.g.
std::vector<BattlePoint> x;
x.push_back(BattlePoint(1, 2));
If you ever find yourself using new[], delete, or delete[], refactor your program immediately to remove such. They are hideously unsafe in virtually every way imaginable. Instead, use resource-managing classes, such as std::unique_ptr, std::vector, and std::shared_ptr.
Regular new can be useful in some situations involving unique_ptr, but else avoid it. In addition, placement new is usually not worth it. Of course, if you're writing a resource-managing class, then you may have to use them as underlying primitives, but that's few and very far between.
Edit: My mistake, I didn't see the very last line of your question. Addressing it:
P.S. 2: I know this can be done through stdlib's vector class, but I'm
avoiding it on purpose.
If you have some campaign against the Standard Library, then roll your own vector replacement. But do not go without a vector class. There's a reason that it must be provided by all conforming compilers.
points = new BattlePoint[size]; // Here be doubts.
P.S. 2: I know this can be done through stdlib's vector class, but I'm avoiding it on purpose.
Most certainly there will be doubts! Use std::vector. Why wouldn't you? There is no reason not to use std::vector, especially if it solves your problem.
std::vector<BattlePoint> bpoints;
bpoints.reserve(size); // there, only alloc'd memory, not initialized it.
bpoints.push_back(some_point); // still need to use push_back to initialize it
I'm sure the question will come - how does std::vector only alloc the memory?!
operator new is the answer. It's the operator that gets called for memory allocation when you use new. new is for construction and initialization, while operator new is for allocation (that's why you can overload it).
BattlePoint* bpoints = ::operator new(size); // happens in reserve
new (bpoints[index]) BattlePoint(some_x, some_y); // happens in push_back
The comp.lang.c++ FAQ has useful things to say on the matter, including attempting to dissuade you from using placement new - but if you really insist, it does have a useful section on placement new and all its pitfalls.
To echo the above answers, I would most certainly point you towards std::vector as it is the best possible solution. Managing your own dynamic arrays in C++ is almost never a good idea, and is almost never necessary.
However, to answer the direct question -- in this situation you can create a default constructor and some mutators to get the desired effect:
class BattlePoint {
public:
// default constructor, default initialize to 0,0
BattlePoint() x(0), y(0) {};
BattlePoint(int x, int y) : x(x), y(y) { };
bool operator==(const BattlePoint &right);
virtual ~BattlePoint();
// mutator functions allow you to modify the classes member values
void set_x(int x_) {x = x_;}
void set_y(int y_) {y = y_;}
private:
int x, y;
};
Then you can initialize this as you are used to in C:
BattlePoint* points = new BattlePoint[100];
for(int x = 0; x < 100; ++x)
{
points->set_x(x);
points->set_y(x * 2);
}
If you're bothered by basically making the BattlePoint class publically mutable, you can keep the mutators private and introduce a friend function specifically for initializing the values. This is a slightly more involved concept, so I'll forgo further explanation on this for now, unless it is needed.
Since you asked :)
Create your BattlePoint class again with a default constructor and mutators, however this time leave the mutators private, and declare a friend function to use them:
class BattlePoint {
public:
// default constructor, default initialize to 0,0
BattlePoint() x(0), y(0) {};
BattlePoint(int x, int y) : x(x), y(y) { };
bool operator==(const BattlePoint &right);
virtual ~BattlePoint();
private:
// mutator functions allow you to modify the classes member values
void set_x(int x_) {x = x_;}
void set_y(int y_) {y = y_;}
int x, y;
friend void do_initialize_x_y(BattlePoint*, int, int);
};
Create a header file that will contain a local function for creating the array of BattlePoint objects. This function will be available to anyone that includes the header, but if named properly then "everyone" should know not to use it.
// BattlePoint_Initialize.h
BattlePoint* create_battle_point_array(size_t count, int* x, int* y);
This function gets defined in the implementation file, along with our friend function that we will "hide" from the outside world:
// BattlePoint_Initialize.cpp
#include <BattlePoint_Initialize.h>
namespace
{
// by putting this function in an anonymous namespace it is only available
// to this compilation unit. This function can only be called from within
// this particular file.
//
// technically, the symbols are still exported, but they are mangled badly
// so someone could call this, but they would have to really try to do it
// not something that could be done "by accident"
void do_initialize_x_y(BattlePoint* bp, int x, int y)
{
bp->set_x(x);
bp->set_y(y);
}
}
// caution, relies on the assumption that count indicates the number of
// BattlePoint objects to be created, as well as the number of valid entries
// in the x and y arrays
BattlePoint* create_battle_point_array(size_t count, int* x, int* y)
{
BattlePoint* bp_array = new BattlePoint[count];
for(size_t curr = 0; curr < count; ++curr)
{
do_initialize_x_y(bp_array[curr], x[curr], y[curr]);
}
return bp_array;
}
So there you have it. A very convoluted way to meet your basic requirements.
While, create_battlepoint_array() could in theory be called anywhere, it's actually not capable of modifying an already created BattlePoint object. The do_initialize_x_y() function by nature of being hidden in an anonymous namespace tucked away behind the initialization code cannot easily be called from anywhere else in your program. In effect, once a BattlePoint object has been created (and initialized in two steps), it cannot be modified further.

RAII and uninitalized values

Just a simple question:
if I had a simple vector class:
class Vector
{
public:
float x;
float y;
float z;
};
Doesnt the RAII concept apply here as well? i.e. to provide a constructor to initialize all values to some values (to prevent uninitialized value being used).
EDIT or to provide a constructor that explicitly asks the user to initialize the member variables before the object can be obstantiated.
i.e.
class Vector
{
public:
float x;
float y;
float z;
public:
Vector( float x_, float y_, float z_ )
: x( x_ ), y( y_ ), z( z_ )
{ // Code to check pre-condition; }
};
Should RAII be used to help programmer forgetting to initialize the value before it's used, or is that the developer's responsibility?
Or is that the wrong way of looking at RAII?
I intentionally made this example ridiculously simple. My real question was to answer, for example, a composite class such as:
class VectorField
{
public:
Vector top;
Vector bottom;
Vector back;
// a lot more!
};
As you can see...if I had to write a constructor to initialize every single member, it's quite tedious.
Thoughts?
The "R" in RAII stands for Resource. Not everything is a resource.
Many classes, such as std::vector, are self-initializing. You don't need to worry about those.
POD types are not self initializing, so it makes sense to initialize them to some useful value.
Since the fields in your Vector class are built-in types, in order to ensure that they are initialized you'll have to do that in a constructor:
class Vector
{
public:
float x;
float y;
float z;
Vector() : x(0.0), y( 0.0), z( 0.0) {}
};
Now, if your fields were classes that were properly written, they should automatically initialize (and clean up, if necessary) by themselves.
In a way this is similar and related to RAII in that RAII means that resources (memory, handles, whatever) are acquired and cleaned up automatically by the object.
I wouldn't exactly say RAII applies here. Remember what the letters stand for: resource acquisition is initialization. You have no resources being acquired here, so RAII doesn't apply.
You could provide a default constructor to Vector; that would remove the need for you to explicitly initialize all the members of VectorField. The compiler would insert code to do that for you.
You use the RAII pattern when you need to do explicit cleanup, and want that cleanup to occur at the same time as another object is implicitly cleaned up. This can occur for memory allocation/deallocation, critical section entry/exit, database connections, etc. In your example, the "floats" are cleaned up automatically so you don't need to worry about them. However, say you had the following function that you called to obtain vectors:
Vector* getMeAVector() {
Vector *v = new Vector();
// do something
return v;
}
And say it was the caller's responsibility to delete the returned vector. If you called this code the following way:
Vector *v = getMeAVector();
// do some stuff with v
delete v;
You'd have to remember to free the vector. If the "stuff" is a long bit of code, which may throw an exception, or have a bunch of return statements in there, you'd have to free the vector with every exit point. Even if you do it, the person who maintains the code by adding another "return" statement or calling some library that throws an exception may not. Instead, you could write a class like this:
class AutoVector
{
Vector *v_;
public:
AutoVector(Vector *v) : v_(v) {}
~AutoVector() { delete v_; }
};
Then, you could obtain the vector like so:
Vector *v = getMeAVector();
AutoVector av(v);
// do lots of complicated stuff including throwing exceptions, multiple returns, etc.
Then you don't have to worry about deleting the vector any more because when av goes out of scope it will be deleted automatically. You can write a little macro to make the "AutoVector av(v)" syntax a little nicer too, if you want.
This is a bit of a contrived example, but if the surrounding code is complicated, or if it can throw exceptions, or someone comes along and adds a "return" statement in the middle, it's nice that the "AutoVector" will free the memory automatically.
You can do the same thing with an "auto" class that enters a critical section in its ctor and exits in its dtor, etc.
If you don't write constructor, the compiler will generate a default constructor for you, and set those values to default (uninitialized values). Provide a default constructor yourself and initialize the values there will be your best way to do this. I don't think it's too complicated to do that. Don't be too lazy :-)