Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 738
Misguided Avatar asked Dec 04 '22 05:12

Misguided


1 Answers

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.

like image 96
Puppy Avatar answered Dec 05 '22 18:12

Puppy