Push Back to Vector in Constructor not working

Can anyone explain why i cannot push_back to a static vector of pointers in the constructor.
I can call attach which is a static method after the constructor runs and that works. But running it in the constructor does nothing.

Incidentally the code works when i tried it in VS.
Is this something related to dynamic memory?

Here is some abbreviated code!

#include "TimerClass.h"

vector<TimerClass*> TimerClass::timeKeeper;

TimerClass::TimerClass(int _val)
	:val(val)
{
	timeKeeper.push_back(this);
}

void TimerClass::attach(TimerClass *obj) {
	timeKeeper.push_back(obj);
}

void TimerClass::display() {
	Serial.println(timeKeeper.size());
}

you are using the right namespace?

std::vector<TimerClass*> TimerClass::timeKeeper;

I recently did something similar that what you are trying, but upon looking at my code, I put it in a begin() function I ran in setup(). I cannot remember why, but perhaps you are trying to add to the array (edit: vector) before it is available to do so.

On the other hand, I was doing some hardware setup in that member function as well, and perhaps it just landed there!

EDIT: this is where I had it:

//declared similarly, you see
std::vector<Brazos*> Brazos::instanceAddress;

//implemented in setup:
void Brazos::begin(int servo, int input)
{
  instanceAddress.push_back(this);

yes i used the correct namespace. The above code was copy pasted of VS but the full version has the std:: before vector

I am experimenting by using a dynamic array of pointers in the constructor to see if this a heap memory issue.

@Ali, the order the constructors are run in is not guaranteed and thus the reason for creating an init function you call in setup().

I thought the order of constructor execution completion runs the body of the constructor after doing everything else in the MIL?

The order of the constructor execution does not necessarily follow the order you have in your code. If the constructor depends on objects created in another constructor, that other constructor may not have run in the expected order.

What does MIL stand for?

Ok! Still a bit confusing as the code ran fine in VS.

I changed it from a vector to a C style array of pointers

TimerClass *TimerClass::chron[NUMBER_OF_TIMERS] = {nullptr};

TimerClass::TimerClass(callback _callback1, callback _callback2)
:trigger(0), subTrigger(0),interval(0),subInterval(0),
 features{TimerMode::FREE,TimerMode::ONE_SHOT,TimerMode::ALARM},
 handler1(nullptr), handler2(nullptr),
 callHandler1(std::move(_callback1)), callHandler2(std::move(_callback2)),
 runOnce(false)
 {
	 //attach the created TimerClass object to chron
	 for(size_t i =0; i < NUMBER_OF_TIMERS; ++i) {
		 //allocate if nullptr
		 if(chron[i] == nullptr) {
			 chron[i] = this;
			 break;
		 }
	 }
}

This seems to work!!

member initializer list

1 Like

@Ali, VS is not gcc-arm and the Particle environment!

OK, after you refered to VS I thought you might mean MS Intermediate Language or Module Intercon Language :joy:

Yes i think this is a platform specific issue.

I am trying to do the above using dynamic memory but am having difficulty getting it to work. Can you take a look?

TimerClass **TimerClass::timers = new TimerClass*[20]{nullptr};
TimerClass::TimerClass(int _val)
	:val(val)
{
	//timeKeeper.push_back(this);
}

void TimerClass::attach(TimerClass *obj) {
	//timeKeeper.push_back(obj);
	for (size_t i = 0; i < 20; ++i) {
				 if(timers[i] == nullptr) {
					 timers[i] = obj;
					 break;
				 }
			 }
}

void TimerClass::display() {
	//cout << timeKeeper.size() << endl;
	for (size_t i = 0; i < 20; ++i) {
		if (timers[i] != nullptr) {
			Serial.println(timers[i]->val);
			break;
		}
	}
}

val returns garbage. I do not know what i am doing wrong.

I guess you are missing an underscore in this

TimerClass::TimerClass(int _val) : val(val) { }

lol!! silly me… Thanks for pointing that out.

Yes very similar to what i did. i had a static attach method

void TimerClass::attach(TimerClass *obj) {
	 TimerClass::timeKeeper.push_back(obj);
 }

Since i am using the TimerClass object in multiple classes.