How can I declare an empty global array, to be initialized in setup?
What I would like to do is this:
#include <ResponsiveAnalogRead.h>const size_t ANALOG_SIZE = 3;const int ANALOG_PINS[ANALOG_SIZE] = {A0,A1,A2};ResponsiveAnalogRead analog_reads[ANALOG_SIZE];void setup() { for(size_t i=0; i<ANALOG_SIZE; i++){ analog_reads[i]=ResponsiveAnalogRead(ANALOG_PINS[i], true, 0.01); }}But the error I get is:
sketch_may29c:5: error: no matching function for call to 'ResponsiveAnalogRead::ResponsiveAnalogRead()' ResponsiveAnalogRead analog_reads[ANALOG_SIZE]; ^Is it impossible to declare an empty array of a given size?
- 1did you try the example sketch that came with the library?jsotola– jsotola2018-05-29 20:46:02 +00:00CommentedMay 29, 2018 at 20:46
- @jsotola yes, that compiles just fine, but that uses only one ResponsiveAnalogRead object.github.com/dxinteractive/ResponsiveAnalogRead also shows how to use multiple, but initializes them globally, not in setup, I want to loop over an array of pin-numbers to initialize multiple of them.RedPixel– RedPixel2018-05-29 20:48:11 +00:00CommentedMay 29, 2018 at 20:48
3 Answers3
As Craig wrote, the declaration of an class typed array will call the default constructor of the class, which is the one without any arguments. The class, that you use, does not provide a default constructor, since it needs it's parameters. You cannot do it this way.
But you can use dynamic allocation. In global scope only declare an array of pointers toResponsiveAnalogRead objects:
ResponsiveAnalogRead *analog_reads[ANALOG_SIZE];This array only holds pointers, that can point toResponsiveAnalogRead objects. The objects themselves are not created yet. Insetup() you can then create the objects dynamically with thenew statement:
analog_reads[0] = new ResonsiveAnalogRead( input_parameters);(Of course you have to replaceinput_parameters with all parameters, that the constructor needs). To call a member of the object, you can dereference it like this:
analog_reads[0]->member_function();If you don't know about pointers yet, you should google for a tutorial (there are plenty), so that you understand the principle behind them.
Important note: Dynamic allocations of memory geht written to the heap in RAM. Since the Arduino (especially the Atmega based ones) has only very limited RAM, dynamic allocations have to be handled with great care. You should not create and delete data often in your program, since this would make swiss cheese out of your heap. But allocating the memory only once in your program and never deleting it, will not be a problem, as long as you don't try to allocate too much memory.
- Makes sense! I have some experience in C, so I do know pointers :) Thanks for elaborating.RedPixel– RedPixel2018-05-30 06:38:24 +00:00CommentedMay 30, 2018 at 6:38
Craig already explained the reason of the error is the lack of a defaultconstructor, and chrisl suggested a reasonable alternative. I would liketo suggest two other alternatives.
Static initialization
You state that you want to do the initialization insetup(), but youdon't explainwhy you want that. I will guess that what youreallywant is to have all those objects in array. The library page providesthis example showing how to statically initialize multiple instances:
ResponsiveAnalogRead analogOne(A1, true);ResponsiveAnalogRead analogTwo(A2, true);The problem with this example is that you don't have an array, so youcannot loop through the instances. This problem, however, can be easilyfixed:
const size_t ANALOG_SIZE = 3;ResponsiveAnalogRead analog_reads[ANALOG_SIZE] = { ResponsiveAnalogRead(A0, true), ResponsiveAnalogRead(A1, true), ResponsiveAnalogRead(A2, true)};Note that you don't need theANALOG_PINS array anymore. And you don'tneed to pass0.01 as the last argument to the constructor, as this isthe default value anyway. This would be my preferred solution: it issimple enough and doesn't increase the number of lines of code.
Patching the library
If youreally want to initialize the array insetup(), then you canpatch the file ResponsiveAnalogRead.h from the library:
- Add default values to all the parameters of the constructor. Forexample:
ResponsiveAnalogRead(int pin=0, bool sleepEnable=0, float snapMultiplier=0.01);- Add a method for setting the pin after initialization:
void setPin(int newPin) { pin = newPin; pinMode(pin, INPUT); }The first change will enable you to compile your code as-is. The secondchange will allow you to update the objects insetup() rather thanoverwriting them (which I don't find very elegant):
for (size_t i = 0; i < ANALOG_SIZE; i++) { analog_reads[i].setPin(ANALOG_PINS[i]); analog_reads[i].enableSleep();}Note that using the default constructor now has the side effect ofsetting pin 0 to input. This should not be a big deal, as theconstructor is called beforesetup(), and all the IO pins are inputsat this point. If you want nevertheless to void that side effect, thenset the default pin to-1, and patch the constructor to only configurethe pin if it's not-1.
Patching the library creates a maintenance burden though: you will haveto reapply the patch each time the library is updated. This may not bethat bad if you know how togit rebase orgit merge, but ideally youwould want to get a pull request accepted by the original maintainer.
Edit: Before patching the library, consider weighting inthisissue and usingthis fork.
Update: Apull request addressing this issue has beenaccepted. As of version 1.2.0, the class has now a default “do nothing”constructor.
- Thanks for an even more elaborate answer! By the way, the reason I want to initialize in setup() is because I want to multiplex these analog pins to 16 channels. I want each multiplexed channel to have its own ResponsiveAnalogRead object. That also means I do not want to get rid of the
ANALOG_PINSarray, because I want to loop over that 16 times :) I considered patching the library after @Craig 's answer, but I have no C++ experience. Thanks for suggesting the issue and the fork, but I've gone with the solution offered by @chrisl already.RedPixel– RedPixel2018-05-30 18:48:46 +00:00CommentedMay 30, 2018 at 18:48
When you declare an array it will call thedefault constructor for the type. ResponsiveAnalogRead does not have a default constructor so it cannot initialize the entries in the array.
Explore related questions
See similar questions with these tags.

