Arduino中的向量

时间:2012-04-03 03:06:58

标签: c++ vector arduino

我在Arduino上制作了“航点”的矢量。每个航点都是一个对象。 Arduino显然需要为航点导航存储多个航路点。但是,不是将这些航点存储在标准的预编程阵列中,用户需要能够添加,删除航点并移动它们。不幸的是,Arduino不提供矢量类型作为内置库。

我目前正在考虑两种选择:

  1. Container for objects like C++ 'vector'? 中,有人发布了一个通用库。它不包含任何索引删除或移动操作。但它确实包含一些内存管理策略。

  2. 我过去曾使用 malloc ,dealloc, calloc 。但我根本不喜欢这个选项,尤其是课程。但这是我在Senario中更好的选择吗?

  3. 哪条路走得更好?

7 个答案:

答案 0 :(得分:53)

Standard C++ for Arduino可能是一种选择。它允许您在Arduino中使用STL vector

答案 1 :(得分:4)

听起来你想要实现一个简单的链表。链接列表允许您移动对象(在您的情况下为航点),而不会产生与C ++向量相关的开销。

这是一个实现on GitHub

答案 2 :(得分:2)

arduino的内存有限,因此您需要知道允许的航路点数。在这种情况下,用于保存分配的航点的存储器指针(地址)的简单数组将提供您需要的序列/顺序。保留一个阵列插槽作为工作区域将允许移动路标(重新排序)。

答案 3 :(得分:1)

您可以编写此LinkedList模板类,并在任何需要的地方简单地调用它:

#ifndef LinkedList_hpp
#define LinkedList_hpp


template <class T>
class ListNode {
  public:
    T element;
    ListNode* next;
    ListNode* prev;

    ListNode(T element, ListNode* prev, ListNode* next) : element(element)
    {
      this->next = next;
      this->prev = prev;
    };
};

template <class T>
class LinkedList  {
  private:
    int length;
    ListNode<T>* head;
    ListNode<T>* tail;
    ListNode<T>* curr;
  public:
    LinkedList();
    LinkedList(const LinkedList<T>&);
    ~LinkedList();
    T& getCurrent();
    T& First() const;
    T& Last() const;
    int getLength();
    void Append(T);
    void DeleteLast();
    void DeleteFirst();
    void DeleteCurrent();
    bool next();
    bool moveToStart();
    bool prev();
    void Delete(T&);
    bool Search(T);
    void Clear();
    void PutFirstToLast();
    void Update(T elem);
    LinkedList& operator = (const LinkedList<T>&);
};

template <class T>
LinkedList<T>::LinkedList() {
    length = 0;
    head = nullptr;
    tail = nullptr;
    curr = nullptr;
}

template <class T>
LinkedList<T>::LinkedList(const LinkedList<T> & list) {
    length = 0;
    head = nullptr;
    tail = nullptr;
    curr = nullptr;

    ListNode<T> * temp = list.head;

    while(temp != nullptr)
    {
        Append(temp->element);
        temp = temp->next;
    }
}

template <class T>
LinkedList<T> & LinkedList<T>::operator=(const LinkedList<T> & list)
{
    Clear();

    ListNode<T> * temp = list.head;

    while(temp != nullptr)
    {
        Append(temp->element);
        temp = temp->next;
    }

    return *this;
}

template <class T>
LinkedList<T>::~LinkedList() {
    Clear();
}

template<class T>
T& LinkedList<T>::getCurrent()
{
  return curr->element;
}

template<class T>
T& LinkedList<T>::First() const
{
  return head->element;
}

template<class T>
T& LinkedList<T>::Last() const
{
  return tail->element;
}

template<class T>
int LinkedList<T>::getLength()
{
  return length;
}

template <class T>
void LinkedList<T>::Append(T element)
{
    ListNode<T> * node = new ListNode<T>(element, tail, nullptr);

    if(length == 0)
        curr = tail = head = node;
    else {
        tail->next = node;
        tail = node;
    }

    length++;

}

template <class T>
void LinkedList<T>::DeleteLast()
{
    if(length == 0)
      return;
    curr = tail;
    DeleteCurrent();
}

template <class T>
void LinkedList<T>::DeleteFirst()
{
    if(length == 0)
      return;
    curr = head;
    DeleteCurrent();
}

template <class T>
bool LinkedList<T>::next()
{
    if(length == 0)
        return false;

    if(curr->next == nullptr)
        return false;

    curr = curr->next;
    return true;
}

template <class T>
bool LinkedList<T>::moveToStart()
{
    curr = head;
    return length != 0;
}

template<class T>
bool LinkedList<T>::prev()
{
    if(length == 0)
        return false;

    if(curr->prev != nullptr)
        return false;

    curr = curr->prev;
    return true;
}

template <class T>
void LinkedList<T>::Delete(T & elem)
{
    if(Search(elem))
        DeleteCurrent();
}

template <class T>
void LinkedList<T>::DeleteCurrent()
{
    if(length == 0)
        return;
    length--;
    ListNode<T> * temp = curr;

    if(temp->prev != nullptr)
        temp->prev->next = temp->next;
    if(temp->next != nullptr)
        temp->next->prev = temp->prev;

    if(length == 0)
        head = curr = tail = nullptr;
    else if(curr == head)
        curr = head = head->next;
    else if(curr == tail)
        curr = tail = tail->prev;
    else
        curr = curr->prev;

     delete temp;
}

template <class T>
bool LinkedList<T>::Search(T elem)
{
    if(length == 0)
        return false;
    if(moveToStart())
        do {
            if(curr->element == elem)
                return true;
        } while (next());
    return false;
}

template <class T>
void LinkedList<T>::PutFirstToLast()
{
  if(length < 2)
    return;
  ListNode<T>* temp = head->next;
  head->next->prev = nullptr;
  head->next = nullptr;
  head->prev = tail;
  tail->next = head;
  tail = head;
  head = temp;
}

template <class T>
void LinkedList<T>::Update(T elem)
{
    if(Search(elem))
        curr->element = elem;
}

template <class T>
void LinkedList<T>::Clear()
{
    if(length == 0)
        return;
    ListNode<T> * temp = head;

    while(temp != nullptr)
    {
        head = head->next;
        delete temp;
        temp = head;
    }

    head = curr = tail = nullptr;

}


#endif

按如下所示使用此类:

LinkedList<int> list;

list.Append(1);
list.Append(2);
list.Append(3);
list.Append(4);

int my_integer;

if(list.moveToStart())
    do{
        my_integer = list.getCurrent();
    }while(list.next());

答案 4 :(得分:0)

如果航点正在使用中,您还可以拥有一个固定的航点结构数组,并在结构中包含一个变量。添加航点时,您必须循环遍历数组,直到找到未使用的结构。

答案 5 :(得分:0)

如果要创建一个int向量,则arduino具有以下内存规范。 在Arduino Uno(和其他基于ATmega的主板)中,一个int存储一个16位(2个字节)的值。这保证了-32.768到32.767的范围(最小值为-2 ^ 15,最大值为(2 ^ 15)-1)。在Arduino Due和其他基于SAMD计算机的主板(例如MKR1000和Zero)中,一个int存储一个32位值(4个字节)。这保证了-2,147,483,648到2,147,483,647的范围(最小值-2 ^ 31和最大值(2 ^ 31)-1)。 See more information here

答案 6 :(得分:0)

我不会在任何安全关键设备上使用 std::vector<> 或任何其他类型,这些类型在运行时在 Arduino 上进行幕后动态内存分配。它使 Arduino 有可能因堆栈溢出而发生严重的、不安全的崩溃。

相反,您需要一个固定大小的内存池来保证运行时安全,它在程序初始化时静态分配或动态分配一次,但在运行时从不增加. 您的“向量”应该是在运行时使用此固定大小内存池的自定义向量类、数组、链表或库。

<块引用>

用户需要能够添加、删除航点并移动它们

在我看来,最简单的方法是使用静态分配的结构数组作为内存池。静态数组中的每个结构体都是一个链表节点。

您有数组中这些节点的固定最大数量,以防止堆栈溢出。添加、“删除”和重新排列航点的顺序现在都是可能的。添加和“删除”只是简单地从链表中删除节点,重新排列将通过更改指向的节点和顺序来完成。

对于安全关键、内存受限的微控制器(例如 Arduino),现在可以以完全安全的方式完成此操作。同样,静态结构数组是您的“内存池”,您将使用手动实现的节点链表,所有节点都位于该静态结构数组中。