-1

I am just a novice in C++ and I am trying to make some of my first classes for my work. However, when thinking about the structure of the class, I am doubting and a little bit confused between a template class and inner parameter instancing using free store memory.

Let's consider a simple example as follows.

1 - Template class

template < unsigned int n, typename T>
class myclass
{

private:

     T _data[n];

public:

     myclass() 
     { 
        for (int i=0;i<n;i++) _data[i] = 0;        
     }

     ~myclass(){}
}

2 - Heap memory use

template < typename T>
class myclass
{

private:

     unsigned int _n;
     T *_data;

public:

     myclass(const unsigned int &m) 
     { 
        _n = m;
        _data = new T[_n];
        for (int i=0;i<n;i++) _data[i] =0.;        
     }

     ~myclass(){ delete [] _data;}
}

Between the two aforementioned methods, which one is better? What is the pros and cons of those two? Would anyone please helping me answering those questions? Thank you very much.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • You don't need the loop in the constructors. You can say `myclass() : _data() {}` and `_data = new T[_n]();` respectively. But neither is better. They do different things. You would use them in different circumstances. – juanchopanza Jul 30 '14 at 06:15
  • 3
    Neither? It looks like your trying to reimplement a `std::vector` or `std::array`. – user657267 Jul 30 '14 at 06:16
  • _'which one is better? What is the pros and cons of those two?'_ That's a too broad question, but I'd always prefer the 1st method, whenever possible. – πάντα ῥεῖ Jul 30 '14 at 06:16
  • There's no reason to pass a `unsigned int` by const ref - just pass by value. The first one requires the size to be determined at compile time. The second one's size can be determined at run time - and you'd better write proper copy constructor and copy assignment operator for it. – T.C. Jul 30 '14 at 06:16
  • The 2nd memory allocation is suitable in cases where the required array size is not determined in advance. – user2672165 Jul 30 '14 at 06:23
  • Use standard class templates instead of writing your own. – n. m. could be an AI Jul 30 '14 at 06:30

3 Answers3

1

Both approaches will work.

The first version of the code will be slightly faster because it does not contain internal allocation. Other benefit - it does not contain any point of failure inside. Con: when you will use it as a local variable that is allocated on the stack, you might meet the stack overflow situation.

The situation is slightly controversial here: on one hand there is nothing wrong in allocating big buffers on the stack, at the same time this should be used with caution. I would not recommend first approach for a library with big number of users who do not know what might be allocated on the stack inside the routines of the library.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
1

If you don't need heap allocation, don't use it. It is slower than stack allocation, and requires the tracking of the allocated object.

But your two examples are really not comparable (it is like comparring std::array<> and std::vector<>):

  • One manipulate stack allocate arrays (if this is enough, stick with it), ala std::array<>, requiring users to specify the size at compile time.

  • The second is manipulating a pointer to a heap allocated array (ala std::vector<>) allowing you to further change the size, by reallocating the buffer. If you need runtime resizing, then you should choose this solution.


Also see When should I use the new keyword in C++?

Community
  • 1
  • 1
quantdev
  • 23,517
  • 5
  • 55
  • 88
0

The first one will:

Initialize two times which is maybe not what you expect!

 T _data[n];  // type must be default constructible, init first time here

 for (int i=0;i<n;i++) _data[i] = 0;  // second init! type must be assignable with int

the second example will also init 2 times:

 _data = new T[_n]; // default constructor of T

 for (int i=0;i<n;i++) _data[i] =0.;  // again assigning a value which is second init

What you are writing is a bad version of std::array or std::vector. Simply don't do it :-)

What you have not considered: What is if any action in your algorithms will throw an exception? Maybe new can not allocate memory and throw or returns nullptr if compiled on a environment which has exceptions disabled, maybe the default constructor or the assignment will throw.

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • Your statement would not be true for built-in types as I see it. – user2672165 Jul 30 '14 at 06:32
  • You are right if you think of 2 step init. But the template accepts also non build-in types. So I like to give a hint to that problem. The problem with throwing still exists with `new` for build-in types. – Klaus Jul 30 '14 at 06:36