Search code examples
c++esp32

Forwarding an object in C++


I am working on a project with an ESP32 and a MCP23017.

In the main program I create an object for the MCP and initialize the address.

Adafruit_MCP23X17 pin_Expander;
const int expander_addr = 0x20; // Adress 0x20 

void setup()
{
    Serial.begin(9600);

    pin_Expander.begin_I2C(expander_addr);
    expander_Init(pin_Expander);
}

Since I use many IOs in the project, I wanted to outsource the initialization of these and wrote a function. I have created a separate header file for the function.

void expander_Init(Adafruit_MCP23X17 pin_Expander)
{
    // Load the GPIOs
    pin_Expander.pinMode(pin1_Motor1, OUTPUT); // I have removed the other pins

    // Set all GPIOs to LOW
    pin_Expander.digitalWrite(pin1_Motor1, LOW); // I have removed the other pins
}

I wonder if this is a legitimate way to pass an object into another function?


Solution

  • Adafruit_MCP23X17 is a C++ class, not some typedef that simulates reference semantics in C, so when you declare your function:

    void expander_Init(Adafruit_MCP23X17 pin_Expander)
    

    you're accepting the object by value, not by reference, which means expander_Init(pin_Expander); copies pin_Expander and passes in the copy. Any mutations to the copy would not typically affect the original version (unless the class is poorly designed†).

    If you want to modify the original version, change the prototype to:

    void expander_Init(Adafruit_MCP23X17& pin_Expander)
                                     // ^ added & to make it accept by reference
    

    which means you'll accept a reference to whatever the caller passed, no copies involved, and anything you do to that reference is equivalent to doing it to the original caller-passed object.


    † I'll note: I wouldn't be surprised if the class was poorly designed, and all instance methods effectively modified global, not per-instance, state (low-level hardware manipulation can often make assumptions like this), so your original code might work just fine, but it's not guaranteed without source code inspection, and it might involve some inefficiencies in the extra copy-and-destroy work that passing-by-reference avoids.