7

I have a class that has (amongst many other things) a pointer to unsigned char that gets deleted and reallocated to store some data from another array. This done with a function

 class MyClass {
  private:
      unsigned char* m_Buffer;
      int m_BufferSize;
  public:
      bool SetBuffer(int iSize, const unsigned char* pArray); 
 };

 bool MyClass::SetBuffer(int iSize, const unsigned char* pArray) {
     bool bOK = false;
     if (pArray != NULL  && iSize > 0) {
         delete [] m_Buffer;
         m_Buffer = new unsigned char[iSize];
         memcpy(m_Buffer,pArray,iSize);
         m_BufferSize = iSize;
         bOK = true;
      }
      return bOK;
  }

I dont like this code at all, and I would really like to replace the pointer with a std::vector<unsigned char>. My question is, how would I perform the memcpy aspect? If I were passing a vector in as argument to my function, I could copy it using iterators, but I have no control over parameter argument type so I am stuck with unsigned char* . Is there a way of using iterators, or sizing the vector to the right size and then accessing its internal array so that I can still copy the data with memcpy ? Or even better something using iterators?? I know I could use a loop and push_back but that seems painfully inefficient to me. Any suggestions will be gratefully received.

Component 10
  • 10,247
  • 7
  • 47
  • 64
mathematician1975
  • 21,161
  • 6
  • 59
  • 101

2 Answers2

20

Actually, iterators are modelled from pointers and therefore pointers within an array are considered to implement the RandomAccessIterator concept.

Therefore:

m_buffer.assign(pArray, pArray + Size);
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Will this automatically resize the vector or would I have to call clear and set the size of it to the size of the array? – mathematician1975 Aug 20 '12 at 09:45
  • @mathematician1975 see [here](http://en.cppreference.com/w/cpp/container/vector/assign). You don't have to call clear, resize or anything. – juanchopanza Aug 20 '12 at 09:47
  • Note that this will *not* reduce the capacity. If you want the vector to use exactly the amount of memory required, and no more, you have to do something like `std::vector( pArray, pArray + Size ).swap( m_buffer );`. – James Kanze Aug 20 '12 at 10:32
  • @JamesKanze: I wonder about the *no more*. As far as I know an implementation is free to allocate whatever capacity it deems suitable, so even though you only set `Size` elements it could perfectly jump to the nearest power of 2 (typical...). Of course, you are right about `assign` not reducing the capacity. – Matthieu M. Aug 20 '12 at 12:19
  • @MatthieuM. Formally, I think you're right. All the standard guarantees is that `capacity() >= size()` when you newly construct an `std::vector`. In practice, for all of the implementations I've seen, `capacity() == size()` _if_ the size can be calculated in constant time before starting initialization of the elements (i.e. constructors where the size is given, or which use random access iterators, as is the case here). – James Kanze Aug 20 '12 at 17:10
0

I really advise you to avoid raw pointers this way. I think that is a better idea to manage std::vectors instead of the raw pointers.

class MyClass {
private:
    std::vector<unsigned char> m_Buffer;
    // No size member is needed, it is stored in m_Buffer
public:
    // No size parameter is needed, it is stored in Array
    void SetBuffer(const std::vector<unsigned char> &Array);
};

void MyClass::SetBuffer(const std::vector<unsigned char> &Array) {
    std::copy(Array.begin(), Array.end(), m_Buffer.begin());
}

Assuming that your dessing forces to have a raw managed for MyClass you will take care of this pointer on copy constructors and operator = (or get rid of it instead):

MyClass::MyClass(const MyClass &Class) {
    m_BufferSize = Class.m_BufferSize;
    m_Buffer = new new unsigned char[m_BufferSize];
    memcpy(m_Buffer, Class.m_Buffer, m_BufferSize); 
}

MyClass::operator =(const MyClass &Class) {
    if (m_Buffer) delete [] m_Buffer;
    m_BufferSize = Class.m_BufferSize;
    m_Buffer = new new unsigned char[m_BufferSize];
    memcpy(m_Buffer, Class.m_Buffer, m_BufferSize); 
}

If you don't take care of the MyClass managed pointers in the copy constructor and operator = you will end with two instances of MyClass managing the same memory.

PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94