Own vector class for arduino (c++) - c++

I added also void Clear()-method.
https://redstoner.com/forums/threads/840-minimal-class-to-replace-std-vector-in-c-for-arduino
https://forum.arduino.cc/index.php?topic=45626.0
I'm asking about this Vector class.
void push_back(Data const &x) {
if (d_capacity == d_size) resize();
d_data[d_size++] = x;
}; // Adds new value. If needed, allocates more space
How to add "insert"-method to this Vector class (arduino use C++ but not have a standard vector methods)?
Vector<Sensor*> sensors;
I have a another class Sensor and I use vector like this.
push.back(new Sensor (1,1,"Sensor_1",2));
Is it possible to add values one by one to this vector class? And how to do it?
I like to ask also other question.
How can I call delete/call destructor for this Vector "sensors" so all pointers are deleted? Or sensors vector is deleted? I want to clear the data and then add data to it.

If you want to add an item to the end of the vector, use the push_back method you've quoted above. If you want to add an item somewhere else in the vector, you'll need to add your own method which re-sizes if necessary, shifts the elements above the insert location up one place and then copies the new element into the correct slot. Something like this (untested):
void insert_at(size_t idx, Data const &data) {
assert(idx < d_size);
if (d_capacity == d_size) {
resize();
}
for (size_t i = d_size; i > idx; --i) {
d_data[i] = std::move(d_data[i - 1]);
}
d_data[idx] = data;
++d_size;
}
As Nacho points out, you might be better off with a linked list if you're going to do a lot of these insert operations, especially if the data you're storing is large and/or has a complex move operator.

Related

C++ N-last added items container

I try to find optimal data structure for next simple task: class which keeps N last added item values in built-in container. If object obtain N+1 item it should be added at the end of the container and first item should be removed from it. It like a simple queue, but class should have a method GetAverage, and other methods which must have access to every item. Unfortunately, std::queue doesn't have methods begin and end for this purpose.
It's a part of simple class interface:
class StatItem final
{
static int ITEMS_LIMIT;
public:
StatItem() = default;
~StatItem() = default;
void Reset();
void Insert(int val);
int GetAverage() const;
private:
std::queue<int> _items;
};
And part of desired implementation:
void StatItem::Reset()
{
std::queue<int> empty;
std::swap(_items, empty);
}
void StatItem::Insert(int val)
{
_items.push(val);
if (_items.size() == ITEMS_LIMIT)
{
_items.pop();
}
}
int StatItem::GetAverage() const
{
const size_t itemCount{ _items.size() };
if (itemCount == 0) {
return 0;
}
const int sum = std::accumulate(_items.begin(), _items.end(), 0); // Error. std::queue doesn't have this methods
return sum / itemCount;
}
Any ideas?
I'm not sure about std::deque. Does it work effective and should I use it for this task or something different?
P.S.: ITEMS_LIMIT in my case about 100-500 items
The data structure you're looking for is a circular buffer. There is an implementation in the Boost library, however in this situation since it doesn't seem you need to remove items you can easily implement one using a std::vector or std::array.
You will need to keep track of the number of elements in the vector so far so that you can average correctly until you reach the element limit, and also the current insertion index which should just wrap when you reach that limit.
Using an array or vector will allow you to benefit from having a fixed element limit, as the elements will be stored in a single block of memory (good for fast memory access), and with both data structures you can make space for all elements you need on construction.
If you choose to use a std::vector, make sure to use the 'fill' constructor (http://www.cplusplus.com/reference/vector/vector/vector/), which will allow you to create the right number of elements from the beginning and avoid any extra allocations.

Append and clear for a list c++

I'm trying to realize two methds append() and clear().
In appened(), I need to newPoint to the end of a list. If the list is empty, then adds newPoint as the first(and only) point in the list.
In clear(),I need to remove all the points in a list.
Can you give me some advice to realize appened and clear.
Here is a code:
//
#pragma once
const int maxListSize = 10;
class Point
{
private:
float x;
float y;
public:
Point(float x0 = 0, float y0 = 0)
{
x = x0;
y = y0;
}
};
class PointList
{
private:
//Data members
int size;
int cursor;
Point points[maxListSize];
public:
PointList();
//List Manipalution operations
void append(Point newPoint);
void clear();
~PointList();
};
*I don't need you to write everything for me, just give me some advice. I would like to realize it by myself. Thank you for helping.
Since you store your list elements by value (Point points[maxListSize]),
it is quite easy to do:
PointList() :size(0) {}
void append(Point newPoint) { points[size++] = newPoint; }
void clear() { size = 0; }
This assumes that your Point object doesn't manage any resource, which is true for this particular example. Otherwise, inserted Point objects should be destroyed in clear.
To get the semantics that you're probably expecting for appending new items, and clearing out existing items, I suggest you look at the placement new operator, and manually calling the destructor of an item in the list.
Currently your class will construct all of the items in the list when you create the list. This can be quite time consuming for complex structures. Then, instead of the constructor for your elements being called, you'll instead be calling the copy-assignment operator, as the items are already constructed.
If you store your array as
char * points[sizeof(Point)*maxListSize];
Any only initialize the items when they're actually added, you avoid the construction cost when you create the list.
Your append function takes it's argument by value. Instead, I recommend you have two append functions. One that takes const&, and the other that takes an rvalue-reference. Then, inside the append function, call the placement new operator on the address of the next location in your array.
To clear the array, simple call the destructor for each element in the array one at a time.

Can't push_back a class into an object vector inside a for loop

I cannot call a function that does a push_back into a vector
void GameState::InitialiseBullet(float x, float y, float vx, float vy)
{
Bullet* bullets = new Bullet();
bullets->SetSize(5.f, 20.f);
bullets->AddFrame("./images/bullet.png");
bullets->Play();
bullets->SetX(x);
bullets->SetY(y);
bullets->velocityX = vx;
bullets->velocityY = vy;
bullets->isActive = true;
gameObjects.push_back(bullets);
}
when it is inside the following for loop
for (auto& object : gameObjects)
{
//Determine the type at runtime
if (dynamic_cast<Player*>(object) != 0)
{
//Process player-specific logic
PlayerLogic(dynamic_cast<Player*>(object), a_fTimeStep);
}
//Determine the type at runtime
if (dynamic_cast<Bullet*>(object) != 0)
{
//Process bullet-specific logic
BulletLogic(dynamic_cast<Bullet*>(object), a_fTimeStep);
}
if (dynamic_cast<Enemy*>(object) != 0)
{
//Process enemy-specific logic
Enemy* enemy = dynamic_cast<Enemy*>(object);
EnemyLogic(enemy, lowerAliens);
if (enemy->GetIsActive() == true)
{
allDead = false;
}
}
//Update and draw our objects
object->Update(a_fTimeStep);
object->Draw();
}
The piece of code that calls the function:
if (createBullet == true)
{
InitialiseBullet(bulletX, bulletY, 0, 500);
createBullet = false;
}
That code works when outside the for loop. However, I need the for loop to provide access to each of my player, enemy and bullet objects. Is there a way to push_back to a vector inside a for loop that is based on the same vector? I get a "Expression: Vector iterators incompatible" error when it's inside the loop. Any ideas? New to C++ programming.
It looks like you are pushing into the same vector you are iterating, that means, you are forcing items realocation and iterator invalidation; in other words - your data moves to different location and used iterator becomes invalid.
I rarely see situation where you really need to iterate and append same vector, so take a look into your code again.
If you really need to do that, iterate this way:
for (size_t i = 0; i < gameObjects.size(); ++i)
{/*Some code*/}
Also using this method you should use gameObjects[i]. instead of it->
It's just a vector of pointers, so it's not very big.
The objects being added is probably even smaller.
You could make a copy of the vector and iterate over the copy while inserting into the real one.
You could put new items into a new, empty vector while you iterate, and then splice them onto the real one at the end.
To delete objects, you could do either of those things, or you could simply set a flag "isZombie" and then remove all the zombies at the end.
These aren't the only answers, but they all work.
When using iterators to loop through your vector you can't in this 'for-loop' modify the vector.
A quick google gave me this; which seemd to fit your case pretty well.
Probably because the push_back ... caused an internal
reallocation in the vector thus all its iterators were invalidated.
Source: http://www.cplusplus.com/forum/beginner/64854/
Do I understand you right when I'm assuming your using iterators due to your error message.
One question you should ask yourself is why you would ever want to add instances to this vector, maybe you should rethink your design slightly to avoid this.

Can't Save structure content

I have the next problem:
I created the structure:
struct Series : vector<Candle>
{
Security Sec;
int LookFor;
int TF;
int Corrector;
string ID;
int line;
Series(){};
Series (int _lookfor);
void Update();
};
Constructor:
Series::Series (int _lookfor)
{
LookFor=_lookfor;
for (int i = 1; i<=LookFor; i++)
{
Candle cantype = Candle(i);
push_back(cantype);
}
}
So, then we call this construcor it fills object by candle-values. LookFor - is a number of candles in the vector-series.
After initialization i want update this serie (if there is more new candle, i want delete last one and insert new on the begining of vector-serie)
void Series::Update()
{
if (size()==LookFor)
{
if (newer(cantype,c1))
{
Candle cantype = Candle(1);
Candle c1 = at(0);
pop_back();
emplace(begin(),cantype);
}
}
I need to initialize a vector of these series:
vector vec;
vec.push_back(Series(3));
And constructor does its job, everithing is fine.
But then i update them:
for (size_t x =0; x<=size()-1;x++) vec[x].Update();
I have a problem: it cann't save changes in vector. In Update method everithing is fine, it inserts needed candle in itself, but then method is ended - the state of vector (each element of vec) has no changes. In method we see changes, but after it vector become after constructor-like, the state still the same.
Tell me, please, what am I doing wrong?
As others already mentioned, do not derive from these containers (could cause nasty errors like missing dtor calls and memory leaks, no virtual destructor is present in these containers). Instead, add the vector as a member or leave it as is, if you do private inheritance.
You may use the iterator interface for such containers:
for(std::vector<Series>::iterator sIt = vec.begin();sIt != vec.end();++sIt) sIt->Update();
For your task, consider using a deque or a list as a circular buffer instead of the vector for the Candles. It would perform better for insertions and therefore allows you to use push_front() instead of emplace() or insert().
Alternatively, you could hold an index of the vector element just past the last element (which should be the first) and just assign the new candle, et voilĂ , you've got a dense circular buffer.
There are implementations of such circular buffers, for example the one of boost:
http://www.boost.org/doc/libs/1_52_0/libs/circular_buffer/doc/circular_buffer.html
Despite logic issues, which could prevent the modification in certain states, I can't see, why your code doesn't work at all, at least not when I went through the snippets you posted.

c++ help passing a vector index to a function

I know how to pass a vector to a function, but how do I pass a vector index to a function, or at least specify which index the function is modifying. For example, I'm working on a Car class and it has a vector if wheel pointers and in order to remove one of the wheels my function looks like this:
Wheel& remove() {
for (int i = 0; i < wheels.size(); i++) {
if (wheels[i].position == wheels.at(i)) {
??
}
what do I need to pass to the function in order to specify which wheel I want removed? When a wheel is removed, the position where it was is still there and can be filled by another wheel. Let's say for example the car had 4 wheels...if I wanted to remove the 2nd index in the wheel vector, what does the function argument for remove() need to take in order to do it? Should I pass in the vector and then the specific index....and if so, what does the syntax look like?
You can just pass an integer to specify which one you would like to remove
void RemoveWheel(int i)
{
if( (i<wheels.size()) and (i>=0) )
wheels.erase(wheels.begin()+i);
}
http://www.cplusplus.com/reference/stl/vector/erase/
If you want to leave the space for another wheel than you should define wheels as a vector of pointers and just delete object at the i-th position and save NULL instead of it.
vector<Wheel *> wheels;
void RemoveWheel(int i)
{
if( (i<wheels.size()) and (i>=0) ) {
delete wheels[i];
wheels[i] = 0;
}
}
Your question is not entirely clear to me, but to remove an element from a vector, given an index i, you can do this:
wheels.erase(wheels.begin() + i);
But this would be better:
auto e = std::remove_if(wheels.begin(), wheels.end(),
[](const Wheel & wheel) {
return wheel.position == wheel;
});
wheels.erase(e,wheels.end());
Although I'm not sure if you want to remove every element that fits that criteria, or just the first. If you would show the logic in pseudocode of what you want to do, that would help.