【问题标题】:How do I modify push_back to store unique vectors如何修改 push_back 以存储唯一向量
【发布时间】:2021-02-07 04:58:30
【问题描述】:

我对向量和模板非常陌生。似乎还不能把我的头绕在他们身上。 代码如下:

template <class T>
class m_vector
{
    int m_iNextIndex;
    int m_iMaxSize;
    T* m_pArray;

public:

    m_vector()
    {
        m_pArray = 0;
        init();
    }

    m_vector(const m_vector<T>& other)
    {
        m_pArray = 0;
        m_iNextIndex = 0;
        m_iMaxSize = 0;
        *this = other;
    }

    ~m_vector()
    {
        if (m_pArray != 0)
            delete [] m_pArray;
    }

    void init()
    {
        m_iMaxSize = VECT_INC_SIZE;
        m_pArray = new T[m_iMaxSize];
        m_iNextIndex = 0;
    }

    inline void push_back(const T& item)
    {
        if (m_iNextIndex >= m_iMaxSize)
        {
            resize(m_iNextIndex + VECT_INC_SIZE);
            m_iNextIndex -= VECT_INC_SIZE;
        }
        m_pArray[m_iNextIndex] = item;
        ++m_iNextIndex;
    }

    void resize(int iNewSize)
    {
        if (iNewSize >= m_iMaxSize)
        {
            T* temp = new T[iNewSize];
            for (int i = 0; i < m_iNextIndex; ++i)
            {
                temp[i] = m_pArray[i];
            }
            delete [] m_pArray;
            m_pArray = temp;
            m_iMaxSize = iNewSize;
        }
        m_iNextIndex = iNewSize;
    }

};

push_back 使用 (x, y) 向量和 (x, y, width, height) 矩形调用。 我认为由于代码具有“m_pArray [m_iNextIndex] = item”,因此我可以简单地添加一个新函数来检查该项目是否唯一,然后再将其添加到向量列表中。所以我编写了一个例程如下:

int inline exists(const &item)
{
  for(int i = 0; i < m_iMaxSize; i++)
  {
    if(m_pArray[i] == item)
      return 1;
  }
  return 0;
}

编译器不高兴。它在if语句上报告了以下错误: “左操作数必须是指针或指向类成员的指针,或算术”

我想我可能需要类似的东西:

if (type == vector)
 if( (m_pArray[i].x == item.x) ....)
else
 if( (m_pArray[i].x == item.x) && (m_pArray[i].width == item.width) )

我在正确的轨道上吗? 如果是这样,我如何检查项目的类型。

谢谢,比尔。

【问题讨论】:

  • exists(const &amp;item)
  • 你能告诉我们你是如何使用你的班级的吗?
  • 请复制完整的错误信息。
  • 当我编译提供的代码时,我得到的第一个错误是ISO C++ forbids declaration of 'item' with no type(参见 bipll 的评论)。一旦我解决了这个问题并且缺少VECT_INC_SIZE 的定义,代码就会编译。虽然最好将minimal reproducible example 中的代码最小化,但该示例仍然需要重现问题。
  • 该问题可能是由VectorRectangle 类没有相等比较运算符引起的。例如。 friend bool operator==(Vector&amp; lhs, Vector&amp; rhs);.

标签: c++ templates vector unique


【解决方案1】:

问题是您的VectorRectangle 缺少比较运算符,例如

friend bool operator== (Vector const& lhs, Vector const& rhs){
    return lhs.x == rhs.x && lhs.y == rhs.y;
} 

但是你们其余的代码不好,需要重写。我已经将我的代码重写为旧式:

注意:不要盲目复制此代码。仅供参考。使用前测试

#define VECT_INC_SIZE 10

// replaced by iterator version
//template< class InputIt, class Size, class OutputIt>
//OutputIt copy_n(InputIt first, Size count, OutputIt result) {
//    while (count-- > 0) {
//        *result++ = *first++;
//    }
//    return result;
//}

template<class InputIt, class OutputIt>
OutputIt copy(InputIt first, InputIt last, OutputIt d_first) {
    while (first != last) {
        *d_first++ = *first++;
    }
    return d_first;
}

template<class T>
T exchange(T& obj, T new_value)
{
    T old_value = obj;
    obj = new_value;
    return old_value;
}

template <class T>
class m_vector
{
private:
    unsigned int size;
    unsigned int capacity;
    T* array;

public:
    m_vector()
    : size(0)
    , capacity(VECT_INC_SIZE)
    , array(new T[VECT_INC_SIZE])
    {}

    m_vector(m_vector<T> const& other)
    : size(other.size)
    , capacity(other.capacity)
    , array(new T[other.capacity]) {
        //copy_n(other.array, size, array);
        copy(other.cbegin(), other.cend(), begin());
    }

    // rule of 3
    m_vector& operator=(m_vector<T> const& other) {
        if (&other != this) {
            if (other.capacity != capacity){
                delete [] exchange(array, new T[other.capacity]);
                capacity = other.capacity;
            }
            size = other.size;
            //copy_n(other.array, size, array);
            copy(other.cbegin(), other.cend(), begin());
        }
        return *this;
    }

    ~m_vector() {
        if (array != 0) delete [] array;
    }


    void push_back(T const& item) {
        if (size >= capacity) {
            reserve(capacity + VECT_INC_SIZE);
        }
        array[size] = item;
        ++size;
    }

    void reserve(unsigned int newCapacity) {
        if (size > capacity) {
            T* const temp = new T[newCapacity];
            //copy_n(array, size, temp);
            copy(cbegin(), cend(), temp);
            delete [] exchange(array, temp);
            capacity = newCapacity;
        }
    }

    bool exists(T const& item) const {
        //for(unsigned int i = 0; i < size; ++i) {
        //    if(array[i] == item) return true;
        //}
        for(T const* it = cbegin(); it != cend(); ++it) {
            if(*it == item) return true;
        }
        return false;
    }

    void erase(T const& item) {
        T* it = begin();
        T* const endIt = end();
        while(it != endIt && *it != item) ++it;
        if (it == endIt) return;
        copy(it + 1, endIt, it);
        --size;
    }

    // iterators
    T* begin() { return array; }
    T* end() { return array + size; }
    T const* cbegin() const { return array; }
    T const* cend() const { return array + size; }
};

class Vector {
private: 
    int x,y;
public:
    Vector() : x(0), y(0) {}
    Vector(int x, int y) : x(x), y(y) {}

    friend bool operator== (Vector const& lhs, Vector const& rhs){
        return lhs.x == rhs.x && lhs.y == rhs.y;
    } 
    friend bool operator!= (Vector const& lhs, Vector const& rhs){
        return !(lhs==rhs);
    } 
};

#include <cstdio>

void VectorInM_Vector(m_vector<Vector> const& vec, Vector const& item) {
    if (vec.exists(item)) printf("Vector found in vector\n");
    else printf("Vector not found in vector\n");
}

int main(){
    m_vector<Vector> vec;
    vec.push_back(Vector(1,1));
    VectorInM_Vector(vec, Vector(1,1));
    m_vector<Vector> vec2(vec);
    vec.erase(Vector(1,1));
    VectorInM_Vector(vec, Vector(1,1));

    VectorInM_Vector(vec2, Vector(1,1));
    vec2 = vec;
    VectorInM_Vector(vec2, Vector(1,1));
}

on compiler explorer/godbolt

【讨论】:

  • 我的新模块应该是“int inline exists(const T &item)”。这是我的问题的更多范围。代码在 QNX 4.25 上运行。不使用 std 库。在运行大约 8 小时后,系统出现了一些内存问题。我认为如果我们可以重新设计 push_back 调用以仅添加唯一向量,那么我们应该能够运行更长时间。我还想限制代码更改以避免数百小时的回归测试。我查看了上面的代码更改,很难检测到我真正需要哪些更改才能使“存在”有效。你能澄清一下吗?
  • 编译器错误信息前面有:Error! E531
  • 使用 Watcom C++32 优化编译器版本 10.6 1989、1996。
  • @billybob 等等什么?这是生产代码吗?你使用的是 1996 年的编译器???如果这段代码通过了测试,那么恐怕测试还不够好。您可以尝试使用此exists 解决方法来“修复”问题。但是,这可能只会将 MTBF 时间从 8 小时更改为 16 小时左右……这不是解决方案。代码存在严重问题,需要修复。
  • 是的,我知道代码有一些问题。由于缺乏工具,我无法诊断。我正在尝试将此作为一种调试方法,以便在我的分析中提供另一个数据点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2013-03-01
  • 2021-06-23
相关资源
最近更新 更多