Why does the usage of 'new' increase the size of the program significantly?

Disclaimer: I'm an intermediate programmer, all the low level C/C++ and microcontroller programming is new to me though. I know how pointers work, but I haven't applied them in this field.

I'm currently embarking on the mystical realm that is microcontroller programming, and I'm running into an anomaly that I can't explain.

I've created a simple program for treating an input pin as a toggle button, nothing fancy. It contains simple boolean logic, calls digitalRead, has two booleans and an unsigned char as members, and takes up three bytes of RAM, according to sizeof. I've put it on Github if you need to know more.

If I create a new instance of this class like

ToggleButton::ToggleButton toggleButton(BUTTON_PIN);

the program's total size (according to the compiler log) is 1218 bytes.

However, if I create the instance with new, like

ToggleButton::ToggleButton* toggleButton = new ToggleButton::ToggleButton(BUTTON_PIN);

the sketch suddenly becomes 1774 bytes.

I can't figure out where this increase in size comes from, or how I can avoid it, because 550 bytes is a pretty significant increase if you only have 32k, and I really want to use C++ and object oriented programming.

Can anyone enlighten me?

I think the 'new' allocates memory, so the functions for memory allocation have to be included.
The Arduino doesn't include unused functions in the compiled code.
A function can use other functions, that is why for example using a single library function can enlarge the code significantly.

If it is a one-time investment, then it is fine by me :). I'd like it if it didn't take 0.5kb, but if it only needs it once then it is not that bad. Thanks!

Yes its a one time investment, as you put it. This is true with any good programming environment, whether you're coding for Arduino, Linux, Windows, whatever. The linker should not include stuff that you didn't use. There are piles and piles of linker switches to configure and customize what's linked, how its linked and so on.

But the bottom line is, once its linked, its linked. You won't incur the same penalty for each call to new.

DEiE:
I can't figure out where this increase in size comes from, or how I can avoid it, because 550 bytes is a pretty significant increase if you only have 32k, and I really want to use C++ and object oriented programming.

Note that you may be doing object oriented programming even if you do not create class instances through the new operator. And the new operator is not a constructor, so there's nothing especially object-oriented in it. Part of the overhead you see is due to the compiler's having to compile/link the new operator itself.

Thank you all for your comments, it is much clearer to me now.


spatula:
Note that you may be doing object oriented programming even if you do not create class instances through the new operator. And the new operator is not a constructor, so there's nothing especially object-oriented in it. Part of the overhead you see is due to the compiler's having to compile/link the new operator itself.

Yes I know. This was a learning project for me for refamiliarization with the C++ syntax, so it was kind of over-engineered. For instance, I had a state pattern stuffed in there to manage the states of the pin. Totally unrealistic and far too complex, I know, but perfect for figuring out how pointers worked again.

In the future I'm going to stick to initializing the objects without new and passing references to these object around, instead of allocating them. This should be enough in most cases. Thanks for your reply!

I don't understand this:

ToggleButton::ToggleButton toggleButton(BUTTON_PIN);

The class name is ToggleButton, not ToggleButton::ToggleButton (unless you are really weird).

Same here:

ToggleButton::ToggleButton* toggleButton = new ToggleButton::ToggleButton(BUTTON_PIN);

PaulS:
I don't understand this:

ToggleButton::ToggleButton toggleButton(BUTTON_PIN);

The class name is ToggleButton, not ToggleButton::ToggleButton (unless you are really weird).

Same here:

ToggleButton::ToggleButton* toggleButton = new ToggleButton::ToggleButton(BUTTON_PIN);

It's in a namespace.

namespace ToggleButton
{
   class ToggleButton
   {
      ...
   };
}

It isn't necessary for this example and I should have left it out, because it only causes confusion. I like the really weird part though ;).

It isn't necessary for this example and I should have left it out, because it only causes confusion.

One of the reasons that we send people down the road when they post just some snippets is because incomplete code causes us to make assumptions.

The real confusion comes from using the same name for two different things. The class and the namespace should NEVER use the same name. Doing so is like the character on the Bob Newhart show with "My brother Darryl, and my other brother Darryl".