How can Arduino's 8 bit Microcontrollers handle C++
It's a misconception that using constructors or C++ in general requires lots of RAM. Plus, to be clear, the AVR processors like the Micro and Uno have separate RAM and PROGMEM (program memory). So, code for functions does not, in itself, use RAM.

As an example, this small program for the Micro:

int main ()
  {
  }


That uses only 206 bytes of PROGMEM and 0 bytes of RAM (according to the IDE).

Sketch uses 206 bytes (0%) of program storage space. Maximum is 28,672 bytes.
Global variables use 0 bytes (0%) of dynamic memory, leaving 2,560 bytes for local variables. Maximum is 2,560 bytes.




Adding in a class, with a constructor, and using that class, increases the memory a bit:

class foo
  {
  public:
  int bar;  // some class variable

  foo ()  // constructor
    {
    bar = 1;
    }
  };  // end of foo


foo nick;  // a global variable
int main ()
  {
  PORTD = nick.bar;
  }


That uses 2 bytes of RAM, and 278 bytes of PROGMEM. Hardly a lot.

Sketch uses 278 bytes (0%) of program storage space. Maximum is 28,672 bytes.
Global variables use 2 bytes (0%) of dynamic memory, leaving 2,558 bytes for local variables. Maximum is 2,560 bytes.




Of course, the more things you do, the more RAM and PROGMEM it takes, however the compiler generates quite efficient code, and the linker strips out things that are not needed by your code.




  Is it that Arduino's library does not contain or utilize features such as constructors or objects (of C++) ...


A lot of libraries use classes and constructors (for example the Serial library, the Print class, and a lot of others). There is nothing inherently RAM-intensive about a constructor. It's just a function that does something, with an implied this pointer to the current instance of the class.




  do lambdas work? (from a comment)


Yes you can use lambdas:

// array of function pointers
void (*doActionsArray []) () =
 {
 [] { Serial.println (0); } ,
 [] { Serial.println (1); } ,
 [] { Serial.println (2); } ,
 [] { Serial.println (3); } ,
 [] { Serial.println (4); } ,
 };

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  doActionsArray [3] ();
  }  // end of setup

void loop () { }





  as long as you don't (extensively) use: the standard library, exceptions, templates ... (from a comment)


Templates can certainly simplify doing things like writing to, or reading from EEPROM and similar. For example:

#include &lt;Arduino.h&gt;  // for type definitions
#include &lt;EEPROM.h&gt;

template &lt;typename T&gt; unsigned int EEPROM_writeAnything (int ee, const T&amp; value)
{
    const byte* p = (const byte*)&amp;value;
    unsigned int i;
    for (i = 0; i &lt; sizeof(value); i++)
        EEPROM.write(ee++, *p++);
    return i;
}

template &lt;typename T&gt; unsigned int EEPROM_readAnything (int ee, T&amp; value)
{
    byte* p = (byte*)&amp;value;
    unsigned int i;
    for (i = 0; i &lt; sizeof(value); i++)
        *p++ = EEPROM.read(ee++);
    return i;
}




The standard library? There are implementations for the Arduino. We have to bear in mind that RAM is limited, however if you are going to do something anyway that involves linked lists, etc. then the Standard Template Library will probably do what you want as efficiently as you could if you coded it "by hand".



The bottom line is you need to be aware of what you are coding on. I have seen examples like this:

float foo [1000];  // hold my readings


That blows the available RAM on a Uno straight away. Nothing to do with C++ per se.



The other thing to be aware of is some tricks you can usefully employ. One common one is to replace:

Serial.println ("Program starting.");


With:

Serial.println (F("Program starting."));


The first example causes the compiler to copy the string "Program starting." from PROGMEM into RAM, using some of your valuable RAM. The second example doesn't.