0

Example: The class (library) uses array of default fixed size. Let's say 64 bytes. In the program, however, you may need bigger size, lets say 128 bytes. What would be the best approach, if you don't want to rewrite the library every time?

I tried to demonstrate this by following WRONG code (using #ifndef #define):

// myClass.h *****************************************

#ifndef myClass_h
#define myClass_h

#ifndef EXAMLPE
#define EXAMLPE 64
#endif

class myClass{
        ...
    private:
        byte myArray[EXAMLPE];  // Use EXAMLPE to allocate array
}

#endif


// Program.ino ***************************************

// Override the default value without modifying the library
#define EXAMLPE 128
#include "myClass.h"
// this does not work because of different scope, says compiler

EDIT: I want make fixed size array as it is easy and it is considered as good practise on 2kb RAM platform

EDIT 2: I don't understand all the arguing in the comment and also why my question is down rated. I'm not a great programmer of course, I do not know anything about vectors, nor templates, and that's why I'm asking here for help.

I'm looking for a method, how to set fixed size array in library from main code in compile time.

And finally: Does anyone know why do I get compile error EXAMPLE was not declared in this scope when I delete #ifndef EXAMPLE ... #endif lines from header? Isn't it suppose to be scope independent?

Combinatix
  • 1,186
  • 3
  • 12
  • 24

4 Answers4

4

Compile-time

If your size is defined at compile time, you could use a template class, with the size as template argument.

template<int EXAMPLE>
class myClass{
        ...
    private:
        byte myArray[EXAMPLE];  
};

or you could use the std::array container.

vs. Run time

However fixed sized arrays are not very flexible. I'd therefore strongly advise to use vectors instead. Not only can you set a default size for your vector, but this size can be adapted dynamically without you having to worry about memory management, copy constructors, assignment operators, etc...

class myClass {
    public: 
        myClass(int mysize=64) : myVector(mysize) {}       
    private:
        std::vector<byte> myVector;  // no size needed here
};
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • Apparently, using dynamic arrays is not recommended on Arduino as it brings problems with RAM fragmentation, stack overflow etc. – Combinatix Aug 01 '16 at 22:51
  • @Combinatix I'd be interested in some reference about these problems. The general remarks I've read about avoiding dynamic memory allocation on arduino were mostly founded on the usual errors with manual allocation. If you're using vectors as explained above you should remain safe. Note that there is more risk of stack overflow with your fixed array because local objects are allocated on the stack which is limited in size whereas with vectors you remain flexible. If you don't want dynamic allocation, the only way out would be the compile time sizing. – Christophe Aug 01 '16 at 23:22
0

C++ does not support runtime sized arrays. Therefore if you do not know at compile time what size of memory you will need an array is the wrong tool for the job. I would instead suggest having your object contain only a pointer, and then use new to dynamically allocate the data block based on some runtime value.

Note the following code is just to demonstrate the idea expressed above and is not tested, and probably does not compile.

class myClass {
private:
    byte *myData;
public:
    myClass(std::size_t dataSize) :
            myData(new byte[dataSize])
    {}
    myClass(const myClass&) = delete;
    myClass(myClass&&) = delete;
    myClass& operator=(const myClass&) = delete;
    myClass& operator=(myClass&&) = delete;
    ~myClass()
    {
        delete[] myData;
    }
};

If on the other hand, the size is known at compile time, but you dont wish to edit the header file every time you need to change the size you could instead use a template class, these allow users to provide compile time parameters when they use the class. For example:

template<size_t dataSize>
class myClass {
private:
    byte myArray[dataSize];
};

The class can then be created with a custom size known at compile time as follows:

auto foo = myClass<128>();
Vality
  • 6,577
  • 3
  • 27
  • 48
  • @Combinatix Then have you looked at the second part of the answer regarding templating? – Vality Aug 01 '16 at 22:19
  • @Combinatix If you think you need to change the size of the array then you do _not_ know how many sensors there will be. If you did there would be no need to worry about the size. You're doing something that's not quite right here...go back and revisit your design and requirements and figure out where your mistake is. – Captain Obvlious Aug 01 '16 at 22:29
  • @Combinatix Do **not** use `new` and `delete` as shown in the proposed solution. There is no need ot manage memory like this in modern C++ and very little reason to do it in previous incarnations of the language. It is problematic, prone to leaks, and just a bad idea all the way around. Instead use `std::array` or `std::vector`. – Captain Obvlious Aug 01 '16 at 22:31
  • @CaptainObvlious I think you have directed this comment to the wrong person, I was just suggesting an answer for how the OP could achieve either a compile time known or runtime known array size in their class. It is Combinatix who asked the original question, not I. – Vality Aug 01 '16 at 22:31
  • @CaptainObvlious In addition, you are assuming an embedded platform has access to the full standard library, including things like vector, what makes you think this the case? I assumed that given the OP was running on an embedded platform they would not have standard library access, else I would have mentioned it. – Vality Aug 01 '16 at 22:32
  • @CaptainObvlious Specifically, please see http://stackoverflow.com/questions/9986591/vectors-in-arduino vectors are not available by default on arduino, and adding support for them involves an extremely bulky library and uses much of the resources of the little micro. – Vality Aug 01 '16 at 22:36
  • 1
    If they aren't available for your platform use an equivalent. I have implementations of both for multiple embedded platforms including arduino. They may not be _standard_ but they do conform to the specs described in the standard. `std::array` (or equivalent) has zero overhead compared to fixed sized arrays. `std::vector` has only a tiny bit of overhead to determine the number of elements available and used. However suggesting `std::array` or `std::vector` or an equivalent is far less misguided than suggesting `new` and `delete. As for taking up to many resources - that's total hogwash! – Captain Obvlious Aug 01 '16 at 22:41
  • @CaptainObvlious I am not sure how to respond to that. I didnt say anything about std::array, and I see nothing wrong with using it but didnt decide to mention it this time. In this case doesnt it offer much advantage. The overhead of a vector is substantial, and significantly higher than that of just using new and delete due to significantly more capabilities, it increases code size significantly, something to be avoided in micro-controller projects. Still, I dont see why this is relevant, the OP said that they knew the size at compile time, I was just giving an option for runtime sizes too. – Vality Aug 01 '16 at 22:48
  • @Vality Could you at least post some code that isn't badly broken? Syntactically correct, and dealing with copy and assignment correctly. – juanchopanza Aug 01 '16 at 22:52
  • _"he overhead of a vector is substantial"_ - No, it's not. What functionality provided by `std::vector` and not use but your program will be eliminated by the linker as dead code. The code that is pulled in should be no greater in size than the code you would write for it yourself. There's certainly a +/- in there for sure but not _substantial_ as you believe. Beyond the extra housekeeping data for beginning, end, and capacity (which you would likely manage yourself as well) I fail to see how you can make that assertion unless you're relying on information that's 20 years old. – Captain Obvlious Aug 01 '16 at 23:00
  • @juanchopanza Ok, the code should compile now, and given this is just an example and not a tutorial on memory management, I have just explicitly deleted copy and assignment to ensure it is clear the example is incomplete. – Vality Aug 01 '16 at 23:06
  • @CaptainObvlious What would have been much more ideal and lightweight would have been http://en.cppreference.com/w/cpp/container/dynarray however that does not appear to be available for arduino and I cannot see that changing any time soon given its rejection from c++14. It would have even in some cases been able to remove the need for dynamic memory management. But otherwise would have at least been simpler and smaller, not allowing resizing, appending and other features which you dont really want to use in an embedded platform...... – Vality Aug 01 '16 at 23:11
  • At very least, a vector generally allocates more space than it needs, having the right to reserve extra, if you know, as the op does that the size requirement will not change that is a waste and inefficient. I do not know of any way to guarantee a vector will not reserve extra memory to allow for fast resizing and appending, is there such a was? – Vality Aug 01 '16 at 23:11
  • Yes, `std::vector` _can_ allocate more memory than is necessary but that doesn't mean it _will_. Any implementation targeting an embedded platform is surely going to take that into account otherwise it could result in limited use. – Captain Obvlious Aug 02 '16 at 02:27
0

Why not substitute the use of an array for a vector and define methods to manipulate the max size of the vector. So something like:

#include <vector>


myClass{

private:
    vector<int> v;
    int maxSize
public:
  myClass(int size){
      v.reSize(size);
      maxSize = size;

  }
  void add(int byte){
      if(v.size()<maxSize){
          v.push_back
      }
  }
}
Dguye
  • 3
  • 2
0

The Arduino IDE does some tricks when converting the .ino files to a single .cpp file

  • create function prototypes
  • eventually reorder #include (?)

This could postpone your

#define EXAMLPE 128

The template solution is best for arduino, I think. vectors and dynamic mem usage is very dangerous with 2kB RAM (on an UNO) only.

datafiddler
  • 1,755
  • 3
  • 17
  • 30