1

I have this code in class constructor:

MqttSensorInterface::MqttSensorInterface(Client& client, String sensorTopic)
{
  this->mqttClient = PubSubClient(client);
  this->sensorTopic = sensorTopic;
  this->askMeasureTopic = sensorTopic + "/askmeasure";
  this->publishMeasureTopic = sensorTopic + "/measure";
}

But just after the constructor is used when a new MqttSensorInterface object is created, the PubSubClient object instantiated in the constructor is destructed (PubSubClient destructor is called). I am new with C++ and dont know if there is something wrong with this code. As the PubSubClient object is instantiated in constructor but the class member mqttClient is set to be this object, which is its scope?

PubSubClient constructor code:

PubSubClient::PubSubClient(Client& client) {
    this->_state = MQTT_DISCONNECTED;
    setClient(client);
    this->stream = NULL;
    this->bufferSize = 0;
    setBufferSize(MQTT_MAX_PACKET_SIZE);
    setKeepAlive(MQTT_KEEPALIVE);
    setSocketTimeout(MQTT_SOCKET_TIMEOUT);
}

EDIT

Solved by using member initializer list this way:

MqttSensorInterface::MqttSensorInterface( Client& client, String sensorTopic): mqttClient(client)
MABC
  • 576
  • 2
  • 11
  • 29
  • 1
    `PubSubClient(wifiClient);` creates a new object, which is then copied or moved to the member variable. The original one gets destroyed when the constructor finishes – UnholySheep Jun 25 '20 at 12:52
  • It depend of the implementation of `PubSubClient::operator=(PubSbuClient const&)`. Maybe there is shared resources ? – Caduchon Jun 25 '20 at 12:53
  • 2
    If that's a problem to you, it's just another reason to [favor member initializer lists](https://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-list) over assignment in the c'tor. – StoryTeller - Unslander Monica Jun 25 '20 at 12:54
  • 2
    No, please don't. At over 300 reputation you should know well enough that important details about your problem (like code) belong in the post body, not in comments. [edit] the code into your question. – StoryTeller - Unslander Monica Jun 25 '20 at 12:56
  • 1
    without a [mcve] this question is unclear. The code you posted can be fine and it can be not fine, depending on the code you didn't post. I would suggest you to write a smaller toy example and ask the same quesiton for that, because too much is missing here – 463035818_is_not_an_ai Jun 25 '20 at 13:05
  • Yes, I edited the post body and the PubSubClient constructor code. I have solved the issue by using member initializer list – MABC Jun 25 '20 at 13:46

1 Answers1

0

When the body of the constructor

MqttSensorInterface::MqttSensorInterface(String sensorTopic)
{
  WiFiClient wiFiClient;
  this->mqttClient = PubSubClient(wifiClient);
  this->sensorTopic = sensorTopic;
  this->askMeasureTopic = sensorTopic + "/askmeasure";
  this->publishMeasureTopic = sensorTopic + "/measure";
}

gets the control the data member mqttClient is already created using the default constructor PubSubClient provided that in the class definition there is no explicit initializer of the data member,

So inside the body in this statement

this->mqttClient = PubSubClient(wifiClient);

there is created a temporary object of the type PubSubClient by means of explicit call of the constructor PubSubClient(wifiClient) and this temporary object is assigned to the data member this->mqttClient using either the copy assignment operator or the move assignment operator. At the end of execution of the statement the temporary object is destroyed.

You could initialize the data member in the mem-initializer list of the constructor during the construction of the data member if it is possible.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • And If I use `new PubSubClient(wiFiClient)` then it wont be destroyed until explicitly destroyed right? – MABC Jun 25 '20 at 13:28
  • 1
    @MABC I have not understood what you mean. In this statement this->mqttClient = PubSubClient(wifiClient); there is created a temporary object PubSubClient(wifiClient); that is assigned to the data member. After the assignment the temporary object will be destroyed. – Vlad from Moscow Jun 25 '20 at 13:31
  • It makes a difference if instead using this statement `this->mqttClient = PubSubClient(wifiClient);` it is used this one `this->mqttClient = **new** PubSubClient(wifiClient);` ? – MABC Jun 25 '20 at 13:41
  • MABC: Those are not equivalent so, yes, there's a difference, but probably not the diff you want. Make a [mcve] so we get all the info we need. – Ted Lyngmo Jun 25 '20 at 13:45
  • @MABC Of course there is a difference. The second case just is invalid if there is used the operator new because this->mqttClient is not a pointer is it? – Vlad from Moscow Jun 25 '20 at 13:47
  • @VladfromMoscow Yes I mean if mqttClient is declared as pointer to PubSubClientObject. Then the object wont be destroyed until it is explicitly destroyed via free(mqttClient) right? – MABC Jun 25 '20 at 14:21