1

Lately, I learned there is a consensus among C++ programmers that the new, delete and delete[] operators should be avoided as often as possible, as already discussed here, here or here. While searching, I even stumbled upon an April Fools' joke stating that these operators would become deprecated in C++20.

I happen to write and maintain a C/C++ program, written in such language in order to carry on useful libraries and classes written by other programmers. As it must run in quite limited environments (i.e., old Linux distributions with the bare minimum in terms of programs), I can't rely on features brought C++11 and later versions (such as smart pointers), and I sticked so far to a mix of C and Java programming habits while expanding my program. Among others, I used quite often dynamic allocation with new and delete - which sounds, of course, to be a problem.

To ease the maintenance of my code by future programmer(s), I would like to minimize dynamic allocation with said keywords in my code. The problem is that my program has to manage some quite large data structures used for (almost) the entire execution. As a consequence, I struggle to figure out why I should avoid dynamic allocation in these situations.

To simplify, consider I have a data structure (modeled as an object) worth 10 Megaoctets which is used for the entire execution of the program and which the size in memory can increase over time. My questions are the following:

  • Is dynamic allocation of the object with new still a bad practice in this particular context ? What are the better alternatives ?

  • Suppose now I instantiate somewhere in my program a new object without using new, do some operations on it which could slightly change its size, then use a method to insert it in my data structure. How does it work, memory-wise, if automatic allocation (as mentioned here) is used ?

Many thanks in advance.

Jef Grailet
  • 547
  • 1
  • 5
  • 7
  • Vectors have been with the language for quite some time, and is often a good replacement for `new[]` and `delete[]`. And many parts of the standard library is implemented in header files only, meaning they are part of your program once you build it and doesn't rely on external libraries. – Some programmer dude Oct 16 '19 at 16:28
  • 1
    Unfortunelty if you are living in a C++03 world you're still going to have `new` and `delete`. You can minimize them though. If you need a collection of thing, use a vector instead of newing up an array. You can also write your own RAII smart pointers, or find a library that has already done so. The big issue with `new` is that you have to manually verify that the memory is deallocated in every control path. That is a pain and is error prone. Hiding the resource allocation and release in a RAII manner makes you code a lot less likely to have these bugs. – NathanOliver Oct 16 '19 at 16:29
  • 1
    Not an answer to the question, but an alterantive solution to your issue. Sometimes, if it is worth the trouble, you can build a development chain for your older platfroms to support newer langauge standards. For instance, we are maintaining a fully c++11 compliant build environment for a older linux target (mandaated by the customer) whose native development environment is only partially c++11 compliant. – dmckee --- ex-moderator kitten Oct 16 '19 at 16:38
  • @NathanOliver Just to make sure (maybe I should have mentioned `vector` in my statement; maybe I'll edit later): let's say I have an array which is several Mo worth (it's the case in practice). I replace it with a vector, without using dynamic allocation (so, in my case, without using `new`), which is a member element of another class. If I dynamically allocate an instance of such class then fill my vector to be equivalent in practice to my former array (again, not using dynamic allocation for the elements), will everything be stored in the heap as if I manually managed the array ? – Jef Grailet Oct 17 '19 at 09:12
  • 1
    @je Yes. Here is a very nice "picture" about it: https://stackoverflow.com/questions/55478523/how-does-stdvector-support-contiguous-memory-for-custom-objects-of-unknown-siz/55478808#55478808 – NathanOliver Oct 17 '19 at 12:22
  • @NathanOliver Many thanks for that. I think I'm getting some idea of how I should handle my memory allocations to minimize `new` now. Maybe I'll update this question later. – Jef Grailet Oct 17 '19 at 12:47
  • @JefGrailet You're welcome. If you wind up coming up with a new question post a new question instead of modifying this one. You don't want to invalidate the answers you already have by changing the question. – NathanOliver Oct 17 '19 at 12:50

2 Answers2

1

You could try using boost smart pointers.

https://www.boost.org/doc/libs/1_71_0/libs/smart_ptr/doc/html/smart_ptr.html

They are very similar to the C++ 11 smart pointers, but available as a library which should work in pre C++ 11 environments. If you decide to go this way, you may also want to look at this

How to include only BOOST smart pointer codes into a project?

Now, I'm wondering if you are confusing the new/delete functions with dynamic allocation in general. Smart Pointers are still dynamic allocation, however they are able to clean themselves up so that you don't have to remember too. That's why they are preferred over using new/delete (malloc/free, etc), they are much less likely to lead to memory leaks.

Automatic allocation is fine when the object lifespan allows it, but if you need the object to persist outside of the function it was declared in, you'll need dynamically allocated memory.

dohashi
  • 1,771
  • 8
  • 12
  • This looks like a nice alternative for my situation. I can't guarantee I will put it as main answer, depending on what other people might provide, but it's still a good answer to me. – Jef Grailet Oct 17 '19 at 09:06
0

Is dynamic allocation of the object with new still a bad practice in this particular context?

Yes, it's bad to have a new in your code mainly because of memory leaks if delete or delete[] isn't called, especially in the face of exceptions.

What are the better alternatives?

Write smart pointers and have them either call new themselves or be called with a new expression:

myUniquePtr<myObj> obj_ptr(new myObj);

and then use RAII to have their destructors call delete or delete[].

Make your smart pointer behave as naked pointer in every other way (overload operator-> etc). Then it'll work in your code with the same syntax as your raw pointers did without having to worry about whether a heap object is deleted at the end of a it's life-cycle no matter what paths the code can take.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54