Topic: Homegrown dynamic array


Author: AllanW <allan_w@my-deja.com>
Date: 2000/01/31
Raw View
In article <fZMf4.396$Q4.1207@nntpserver.swip.net>,
  "Pablo de Heras Ciechomski" <d96pd@efd.lth.se> wrote:
>
> > Yes, that's much better. However, it lacks a copy constructor,
> > which is dangerous, since the compiler generated one will do
> > the wrong thing. If you don't want to allow copying, declare
> > the copy constructor private and don't implement it. If you
> > want copying, implement an appropriate copy constructor.
>
> Thanks for the tip, private is probaly best.

The same remarks also apply to operator=(), for the same reason.
> > The following might corrupt your heap and possibly crash
> > your program (or even the computer), if used with your
> > CFT_Array:

    int main()
    {
       CFT_Array<int> a1, a2;
       a1.Create(10);
       a2 = a1;
    }

--
Allan_W@my-deja.com is a "Spam Magnet," never read.
Please reply in newsgroups only, sorry.


Sent via Deja.com http://www.deja.com/
Before you buy.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Pablo de Heras Ciechomski <d96pd@efd.lth.se>
Date: 2000/01/13
Raw View
Hi,

I've made this dynamic array because I have a New Year resolution not to use
STL
:=)

A usage example is this:

CFT_Array array;
array.Create(5,sizeof(CFT_ComplexClass));

((CFT_ComplexClass*)array[0])->GetComplexNumber();

I'm concerned with the speed of the overloaded [] member method. It uses a
multiply fo each array acces, which I don't know if it will be optimized by
the compiler.

Another way would be to use

ComplexClass *array=new ComplexClass[5];

array[0].GetComplexNumber();

I hope they are equal.

/Thanks in advance

--
/Pablo de Heras Ciechomski
Computer Science and Technology student
at Lund Institute of Technology in Sweden

Here is code for the array
____________________________________________________________________

#ifndef CFT_ARRAY_H
#define CFT_ARRAY_H

class CFT_Array
{
public:
  CFT_Array()
  {
    m_pArray=0;
    m_nNbrElements=0;
    m_nElementSize=0;
  };

  ~CFT_Array()
  {
    Delete();
  };

  int GetNbrElements()
  {
    return m_nNbrElements;
  }

  void Create(int nElements,int nSize)
  {
    Delete();
    m_nNbrElements=nElements;
    m_nElementSize=nSize;
    m_pArray=new char[m_nNbrElements*m_nElementSize];
  }

  void* operator[](int nNbr)
  {
    return (void*)&m_pArray[m_nElementSize*nNbr];
  }

protected:
  void Delete()
  {
    delete [] m_pArray;
    m_pArray=0;
    m_nNbrElements=0;
    m_nElementSize=0;
  }

  int   m_nNbrElements;
  int   m_nElementSize;
  char  *m_pArray;
};

#endif



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/01/14
Raw View
Pablo de Heras Ciechomski wrote:
>
> Hi,
>
> I've made this dynamic array because I have a New Year resolution not to use
> STL
> :=)
>
> A usage example is this:
>
> CFT_Array array;
> array.Create(5,sizeof(CFT_ComplexClass));
>
> ((CFT_ComplexClass*)array[0])->GetComplexNumber();

With your class CFT_array below, this is an access to
uninitialized memory. Unless CFT_ComplexClass is a POD
_and_ CFT_ComplexClass::GetComplexNumber() doesn't
read any member variable (unless it has written it
before), this code causes undefined behaviour.

>
> I'm concerned with the speed of the overloaded [] member method. It uses a
> multiply fo each array acces, which I don't know if it will be optimized by
> the compiler.

If the compiler cannot optimize this, it likely won't optimize
the implicit multiplication on normal array access either.

>
> Another way would be to use
>
> ComplexClass *array=new ComplexClass[5];
>
> array[0].GetComplexNumber();
>
> I hope they are equal.

Only if ComplexClass is POD (in which case the above
caveat of GetComplexNumber still applies). Otherwise,
the new expression default-constructs each member of
the array, while your code doesn't.

[...]

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Ralph D. Ungermann" <ungermann@flexis.de>
Date: 2000/01/14
Raw View
Pablo de Heras Ciechomski wrote:
[...]
> I'm concerned with the speed of the overloaded [] member method. It uses a
> multiply fo each array acces, which I don't know if it will be optimized by
> the compiler.
[...]

Most compilers have a switch to generate assembler code instead of
objects.
There you can dig in and see. And what you see is what you get!


rdu


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Pablo de Heras Ciechomski" <d96pd@efd.lth.se>
Date: 2000/01/14
Raw View
Thanks for your answers. I've come up with this instead, a template class. I
reread chapter 13 in Bjarnes book and suddenly I saw the light :)

--
/Pablo de Heras Ciechomski
Computer Science and Technology student
at Lund Institute of Technology in Sweden

If anyone is interested here is the code.

#ifndef CFT_ARRAY_H
#define CFT_ARRAY_H

template <class CType> class CFT_Array
{
public:
  CFT_Array();
  ~CFT_Array();
  void Delete();

  void Create(int nElements);
  CType& operator[](int nIndex);
  int Size();

protected:
  int    m_nSize;
  CType *m_pArray;
};


template<class CType> CFT_Array<CType>:: CFT_Array()
{
  m_nSize=0;
  m_pArray=0;
}

template<class CType> CFT_Array<CType>:: ~CFT_Array()
{
  Delete();
}


template<class CType>void CFT_Array<CType>:: Delete()
{
  delete [] m_pArray;
  m_nSize=0;
}

template<class CType>inline void CFT_Array<CType>:: Create(int nElements)
{
  Delete();
  m_pArray=new CType[nElements];
  if (m_pArray) m_nSize=nElements;
}

template<class CType>inline CType& CFT_Array<CType>:: operator[](int nIndex)
{
  return m_pArray[nIndex];
}

template<class CType>inline int CFT_Array<CType>:: Size()
{
  return m_nSize;
}

#endif




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Pablo de Heras Ciechomski" <d96pd@efd.lth.se>
Date: 2000/01/14
Raw View
> > A usage example is this:
> >
> > CFT_Array array;
> > array.Create(5,sizeof(CFT_ComplexClass));
> >
> > ((CFT_ComplexClass*)array[0])->GetComplexNumber();
>
> With your class CFT_array below, this is an access to
> uninitialized memory. Unless CFT_ComplexClass is a POD
> _and_ CFT_ComplexClass::GetComplexNumber() doesn't
> read any member variable (unless it has written it
> before), this code causes undefined behaviour.

What's POD? Isn't the class just a struct, the methods are somewhere else in
memory.

> > I'm concerned with the speed of the overloaded [] member method. It uses
a
> > multiply fo each array acces, which I don't know if it will be optimized
by
> > the compiler.
>
> If the compiler cannot optimize this, it likely won't optimize
> the implicit multiplication on normal array access either.

Yep it really isn't a good way of making a dynamic array.

>
> >
> > Another way would be to use
> >
> > ComplexClass *array=new ComplexClass[5];
> >
> > array[0].GetComplexNumber();
> >
> > I hope they are equal.
>
> Only if ComplexClass is POD (in which case the above
> caveat of GetComplexNumber still applies). Otherwise,
> the new expression default-constructs each member of
> the array, while your code doesn't.

I don't think I follow. What is POD?

--
/Pablo de Heras Ciechomski
Computer Science and Technology student
at Lund Institute of Technology in Sweden


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Pablo de Heras Ciechomski" <d96pd@efd.lth.se>
Date: 2000/01/14
Raw View
> Yes, that's much better. However, it lacks a copy constructor,
> which is dangerous, since the compiler generated one will do
> the wrong thing. If you don't want to allow copying, declare
> the copy constructor private and don't implement it. If you
> want copying, implement an appropriate copy constructor.

Thanks for the tip, private is probaly best.

>
> The following might corrupt your heap and possibly crash
> your program (or even the computer), if used with your
> CFT_Array:
>
> void foo(CFT_Array<std::string>) {}

Ah here the array is copied as an argument, got you, thanks.

>
> int main()
> {
>   CFT_Array<std::string> array;
>   array.Create(10);
>   foo(array);
> }


>
> Also, since you made Delete() public, you should set the
> internal pointer to NULL in it (else neither destruction
> nor Create will succeed after the user called Delete).
> Alternatively, make Delete private.

Yep, did that in the old version, but here the error slipped through, thanks
again.

/Pablo de Heras Ciechomski




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/01/15
Raw View
Pablo de Heras Ciechomski wrote:
....
> > With your class CFT_array below, this is an access to
> > uninitialized memory. Unless CFT_ComplexClass is a POD
> > _and_ CFT_ComplexClass::GetComplexNumber() doesn't
> > read any member variable (unless it has written it
> > before), this code causes undefined behaviour.
>
> What's POD? Isn't the class just a struct, the methods are somewhere else in
> memory.

No - some aspects of C++ classes make them incompatible with C structs.
For instance, objects of polymorphic types need to store some per-object
data that identifies the dynamic type of the object, typically a vtable
pointer. POD stands for "Plain Old Data". It basically represents a set
of restrictions on C++ types; objects of types that meet those
restrictions are simple enough to be safely exchanged with C code.

Specifically:
Section 8.5.1 p1: "An _aggregate_ is an array or class (clause 9) with
no user-declared constructors (12.1), no private or protected non-static
data members (clause 11), no base classes (clause 10), and no virtual
functions (10.3)."

Section 3.9 p10: "Scalar types, POD-struct types, POD-union types
(clause 9), arrays of such types and _cv-qualified_ version of these
types (3.9.3) are collectively called _POD types_."

Section 9 p4: "A _POD-struct_ is an aggregate class that has no
non-static data members of type pointer to member, non-POD-struct,
non-POD-union (or array of stuch types) or reference, and has no
user-defined copy assignment operator and no user-defined destructor.
Similarly, a _POD-union_ is an aggregate union that [same description].
A _POD-class_ is a class that is either a POD-struct or a POD-union."

Use dejanews to locate my message to comp.std.c++ dated 1999-09-15
titled "Re: why does POD matter" for a complete list of differences
between the handling of POD and non-POD types. Among the many
differences are differences in the way that they're initialized.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/01/15
Raw View
Pablo de Heras Ciechomski wrote:
>
> Thanks for your answers. I've come up with this instead, a template class. I
> reread chapter 13 in Bjarnes book and suddenly I saw the light :)

Yes, that's much better. However, it lacks a copy constructor,
which is dangerous, since the compiler generated one will do
the wrong thing. If you don't want to allow copying, declare
the copy constructor private and don't implement it. If you
want copying, implement an appropriate copy constructor.

The following might corrupt your heap and possibly crash
your program (or even the computer), if used with your
CFT_Array:

void foo(CFT_Array<std::string>) {}

int main()
{
  CFT_Array<std::string> array;
  array.Create(10);
  foo(array);
}

Also, since you made Delete() public, you should set the
internal pointer to NULL in it (else neither destruction
nor Create will succeed after the user called Delete).
Alternatively, make Delete private.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]