How to fill an array with objects pointers ?

Hello,
I am posting here my question because I did not find any answers on the internet.

I have two classes. An environment and a container one.
In the environment, I have a queue, which is just an array of containers pointer. I fill the queue and try to read it but get an unexpected output. Here is the code

here is the test.h

#ifndef Test_h
#define Test_h

#include "Arduino.h"

class Container
{
  public:
    Container(String name);
    String str();
  private:
    String _name;
};

class Environment
{
  public:
    Environment();
    void readQueue();
    void addQueue(Container* container, int i);
  private:
    Container* _queue[];
};

#endif

here is the test.cpp

#include "Test.h"
#include "Arduino.h"

Container::Container(String name){
  String _name = name;
}

String Container::str(){
  return _name;
}

Environment::Environment(){
  Container* _queue[4];
}

void Environment::readQueue(){
  for (int n=0; n<4; n++)
    {
      Serial.println(n);
      if (_queue[n]==NULL){
        Serial.println("empty");
      }else{
        Serial.println(_queue[n]->str());
      }
    }
}

void Environment::addQueue(Container* container, int i){
  _queue[i] = container;
}

here is my main file

#include <Test.h>

Environment environment;
Container container("test number one");

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

void loop() {
  environment.addQueue(&container, 1);
  environment.readQueue();
  delay(100);
  Serial.println("-----------");
}

and here is the output I get

0

1

2
2�
3
empty

when I was expecting to get this instead

0
empty
1
test number one
2
empty
3
empty

Any ideas why?

manuK:
Any ideas why?

whoops!

Container::Container(String name) {
  String _name = name;
}

I am sorry, I am a beginner. But I don't get your answer. What do you mean by whoops ?

here you create a class with a String member called _name:

class Container
{
  public:
    Container(String name);
    String str();
  private:
    String _name;
};

in your constructor you create a new local variable called _name:

Container::Container(String name) {
  String _name = name;
}

the local variable is destroyed when the constructor ends...

try:

Container::Container(String name) {
  _name = name;
}

and assign the argument to the class member, as you probably want to do.
:wink:

Sorry my mistake. So I change the constructor to avoid create a new local variable.
But my output is weirder. Here is just an extract.

0
⸮⸮⸮Iw⸮⸮⸮⸮⸮ح⸮⸮⸮⸮⸮o⸮⸮7⸮⸮⸮⸮/⸮⸮⸮⸮⸮⸮⸮f⸮⸮⸮⸮⸮⸮_;⸮?⸮⸮M_t⸮⸮⸮⸮p⸮y^o⸮?⸮Y⸮]߫⸮⸮⸮띵/⸮ ⸮}⸮^⸮⸮յ⸮⸮⸮⸮⸮K⸮0
0
0
0
0
0
0
0
⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮9Ha⸮6#⸮Ve⸮!⸮⸮6⸮!ܭ⸮o⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

manuK:
Sorry my mistake. So I change the constructor to avoid create a new local variable.
But my output is weirder. Here is just an extract.

class Container
{
  public:
    Container(String name);
    String str();
  private:
    String _name;
};

class Environment
{
  public:
    Environment();
    void readQueue();
    void addQueue(Container* container, int i);
  private:
    Container* _queue[];
};

Container::Container(String name) {
  _name = name;
}

String Container::str() {
  return _name;
}

Environment::Environment() {
  Container* _queue[4];
}

void Environment::readQueue() {
  for (int n = 0; n < 4; n++)
  {
    Serial.println(n);
    if (!_queue[n]) {
      Serial.println("empty");
    } else {
      Serial.println(_queue[n]->str());
    }
  }
}

void Environment::addQueue(Container* container, int i) {
  _queue[i] = container;
}

Environment environment;
Container container("test");

void setup() {
  Serial.begin(9600);
  environment.addQueue(&container, 0);
  environment.readQueue();
  Serial.println("-----------");
}

void loop() {

}

Ok, thank you for your patience, your code works.

But I still have a few questions :

  • What is the difference between if (!_queue[n]){ and if (_queue[n] == NULL){?

  • Why when I put all the declaration and definition in exterior h and cpp file the program is not working (previous error reappear)?

  • Also, when i put for example

Serial.println("-----------");
  delay(1000);

in the loop function, the program is not working any more also, why?

  • And a last question, I previously developed my program (who is a kind of super thermostat for a brewery) in python, because I am more familiar with this language and it was more easy for me to write all the unit tests, what is the c++ equivalent of push and pop ? I find out with the std::queue::push() and std::queue::pop() of the queue library, but this is not implemented in arduino. What is the alternative ?

whoops again!

I thought you'd be able to find that one, since you did exactly the same error twice. ::slight_smile:

Environment::Environment() {
  Container* _queue[4];
}

similarly, this created a 4 element array local to the constructor.

#include "Test.h"

Environment environment;
Container container("test");

void setup() {
  Serial.begin(9600);
  environment.addQueue(&container, 0);
  environment.readQueue();
  Serial.println("-----------");
}

void loop() {

}

Test.h:

#ifndef TEST_H
#define TEST_H
#include "Arduino.h"

class Container
{
  public:
    Container(String name);
    String str();
  private:
    String _name;
};

class Environment
{
  public:
    Environment();
    void readQueue();
    void addQueue(Container* container, int i);
  private:
    Container* _queue[4];
};

#endif

Test.cpp

#include "Test.h"

Container::Container(String name) {
  _name = name;
}

String Container::str() {
  return _name;
}

Environment::Environment() {
}

void Environment::readQueue() {
  for (int n = 0; n < 4; n++)
  {
    Serial.println(n);
    if (!_queue[n]) {
      Serial.println("empty");
    } else {
      Serial.println(_queue[n]->str());
    }
  }
}

void Environment::addQueue(Container* container, int i) {
  _queue[i] = container;
}

To answer your questions,

plain old C style array sizes are not mutable run-time. you can look into std::vector, but on an MCU you will have problems with dynamic allocation and your micro's limited SRAM.

manuK:

  • What is the difference between
if (!_queue[n]){

and

if (_queue[n] == NULL){

just syntax but C++ is migrating away from NULL (#define NULL 0) for pointer comparisons.

you should use the preferred keyword nullptr

Ok I start to understand. Thank you for everything.