I have two compilers on my hardware C++ and C89
I\'m thinking about using C++ with classes but without polymorphism (to avoid vtables). The main r
For a very resource constrained target such as 4KB of RAM, I'd test the waters with some samples before committing a lot of effort that can't be easily ported back into a pure ANSI C implementation.
The Embedded C++ working group did propose a standard subset of the language and a standard subset of the standard library to go with it. I lost track of that effort when the C User's Journal died, unfortunately. It looks like there is an article at Wikipedia, and that the committee still exists.
In an embedded environment, you really have to be careful about memory allocation. To enforce that care, you may need to define the global operator new()
and its friends to something that can't be even linked so that you know it isn't used. Placement new
on the other hand is likely to be your friend, when used judiciously along with a stable, thread-safe, and latency guaranteed allocation scheme.
Inlined functions won't cause much problem, unless they are big enough that they should have been true functions in the first place. Of course the macros their replacing had that same issue.
Templates, too, may not cause a problem unless their instantiation runs amok. For any template you do use, audit your generated code (the link map may have sufficient clues) to make certain that only the instantiations you intended to use happened.
One other issue that may arise is compatibility with your debugger. It isn't unusual for an otherwise usable hardware debugger to have very limited support for interaction with the original source code. If you effectively must debug in assembly, then the interesting name mangling of C++ can add extra confusion to the task.
RTTI, dynamic casts, multiple inheritance, heavy polymorphism, and exceptions all come with some amount of runtime cost for their use. A few of those features level that cost over the whole program if they are used, others just increase the weight of classes that need them. Know the difference, and choose advanced features wisely with full knowledge of at least a cursory cost/benefit analysis.
In an small embedded environment you will either be linking directly to a real time kernel or running directly on the hardware. Either way, you will need to make certain that your runtime startup code handles C++ specific startup chores correctly. This might be as simple as making sure to use the right linker options, but since it is common to have direct control over the source to the power on reset entry point, you might need to audit that to make certain that it does everything. For example, on a ColdFire platform I worked on, the dev tools shipped with a CRT0.S module that had the C++ initializers present but comment out. If I had used it straight from the box, I would have been mystified by global objects whose constructors had never run at all.
Also, in an embedded environment, it is often necessary to initialize hardware devices before they can be used, and if there is no OS and no boot loader, then it is your code that does that. You will need to remember that constructors for global objects are run before main()
is called so you will need to modify your local CRT0.S (or its equivalent) to get that hardware initialization done before the global constructors themselves are called. Obviously, the top of main()
is way too late.
A good reason and sometimes the only reason is that there is still no C++ compiler for the specific embedded system. This is the case for example for Microchip PIC micro-controllers. They are very easy to write for and they have a free C compiler (actually, a slight variant of C) but there is no C++ compiler in sight.
In general no. C++ is a super set of C. This would be especially true for for new projects.
You are on the right track in avoiding C++ constructs that can be expensive in terms of cpu time and memory foot print.
Note that some things like polymorphism can be very valuable - the are essentially function pointers. If you find you need them, use them - wisely.
Also, good (well designed) exception handling can make your embedded app more reliable than an app that handles things with traditional error codes.
The Technical Report on C++ Performance is a great guide for this sort of thing. Note that it has a section on embedded programming concerns!
Also, ++ on the mention of Embedded C++ in the answers. The standard is not 100% to my tastes, but it is a good bit of reference when deciding what parts of C++ you might drop.
While programming for small platforms, we disable exceptions and RTTI, avoided virtual inheritance, and paid close attention to the number of virtual functions we have lying around.
Your friend is the linker map, though: check it frequently, and you'll spot sources of code and static memory bloat quickly.
After that, the standard dynamic memory usage considerations apply: in an environment as restricted as the one you mention, you may want to not use dynamic allocations at all. Sometimes you can get away with memory pools for small dynamic allocs, or "frame-based" allocation where you preallocate a block and throw out the whole thing later.
The human mind deals with complexity by evaluating as much as possible, and then deciding what's important to focus on, and discarding or depreciating the rest. This is the entire underpinning behind branding in Marketing, and largely, icons.
To combat this tendency I prefer C to C++, because it forces you to think about your code, and how it's interacting with the hardware more closely - relentlessly close.
From long experience it is my belief that C forces you to come up with better solutions to problems, in part, by getting out of your way and not forcing you to waste lots of time satisfying a constraint some compiler-writer thought was a good idea, or figuring out what's going on "under the covers".
In that vein, low level languages like C have you spending a lot of time focused on the hardware and building good data-structure/algorithm bundles, while high level languages have you spending a lot of time scratching your head wondering what's going on in there, and why you can't do something perfectly reasonable in your specific context and environment. Beating your compiler into submission (strong typing is the worst offender) is NOT a productive use of time.
I probably fit the programmer mold well - I like control. In my view, that's not a personality flaw for a programmer. Control is what we get paid to do. More specifically, FLAWLESSLY control. C gives you much more control than C++.
The only reason to prefer C IMHO would be if the C++ compiler for your platform is not in a good shape (buggy, poor optimization, etc).