Class using "new" operator

Hi,

Is it usual to rely completly on the new operator in constructors/copy constructors. What if new trows an exception? The application ends and that's it? The new operator can be placed where it can't be catch like in constructor initialization list. What kind of practice I should adopt when using "new" in those cases?

Thanks


The sample code below is taken from here...
http://msdn.microsoft.com/en-us/library/dd293665.aspx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class MemoryBlock
{
public:

   // Simple constructor that initializes the resource.
   explicit MemoryBlock(size_t length)
      : _length(length)
      , _data(new int[length])
   {
      std::cout << "In MemoryBlock(size_t). length = "
                << _length << "." << std::endl;
   }

   // Destructor.
   ~MemoryBlock()
   {
      std::cout << "In ~MemoryBlock(). length = "
                << _length << ".";
      
      if (_data != NULL)
      {
         std::cout << " Deleting resource.";
         // Delete the resource.
         delete[] _data;
      }

      std::cout << std::endl;
   }

   // Copy constructor.
   MemoryBlock(const MemoryBlock& other)
      : _length(other._length)
      , _data(new int[other._length])
   {
      std::cout << "In MemoryBlock(const MemoryBlock&). length = " 
                << other._length << ". Copying resource." << std::endl;

      std::copy(other._data, other._data + _length, _data);
   }

   // Copy assignment operator.
   MemoryBlock& operator=(const MemoryBlock& other)
   {
      std::cout << "In operator=(const MemoryBlock&). length = " 
                << other._length << ". Copying resource." << std::endl;

      if (this != &other)
      {
         // Free the existing resource.
         delete[] _data;

         _length = other._length;
         _data = new int[_length];
         std::copy(other._data, other._data + _length, _data);
      }
      return *this;
   }

   // Retrieves the length of the data resource.
   size_t Length() const
   {
      return _length;
   }

private:
   size_t _length; // The length of the resource.
   int* _data; // The resource.
};

Is it usual to rely completly on the new operator


these days you should not be using have to use new and delete. look at smart pointers e.g.
http://en.cppreference.com/w/cpp/memory/unique_ptr

not sure why you'd want to use c-style arrays either.
Last edited on
So if new and delete are obsoletes, how could I rewrite this piece of code to be in "these days" :-)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
template <class T>
class WndMessageMaps
{
private:
    typedef struct MsgProc { UINT uMsg; T pProc; } *MSGPROC;
    MSGPROC table_;
    INT size_;
    INT index_;
public:
    // constructor
    WndMessageMaps(INT nElements = 8) :
        table_{ new (std::nothrow) MsgProc[nElements] },
        size_{ nElements },
        index_{ 0 }
    {
        if (table_ == NULL)
        {
            size_ = 0;
        }
    }

    T find(UINT uMsg)
    {
        for (int i = 0; i < index_; ++i)
        {
            if (table_[i].uMsg == uMsg)
            {
                return table_[i].pProc;
            }
        }
        return NULL;
    }

    // other stuff below
    
}

That's a different piece of code isn't it??
I'm not sure how you'd use that nothrow constant in conjunction with a std::unique_ptr to be honest.
Last edited on
That's a different piece of code isn't it??


That's mine from a window message map in a window class.
Last edited on
Unique_ptr handles ownership of a pointer, but I think you still need new to allocate the pointed-at object in the first place.

If you have a unique_ptr to an object and an exception gets thrown (such as when you're out of memory), the pointed-at object will get deleted if the unique_ptr gets deleted. Of course, if the destructor does anything to try to allocate memory, or calls something that tries to allocate memory, then that code is likely to throw an exception too.....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
template <class T>
class WndMessageMaps
{
private:
    struct MsgProc { UINT uMsg; T pProc; };
    std::vector<MsgProc> table_;

    INT index_;
public:
    // constructor
    WndMessageMaps(INT nElements = 8) :
        table_(nElements),

        index_{ 0 }
    {




    }

    T find(UINT uMsg)
    {
        for (int i = 0; i < index_; ++i)
        {
            if (table_[i].uMsg == uMsg)
            {
                return table_[i].pProc;
            }
        }
        return NULL;
    }

    // other stuff below
    
}
By the way: it's generally not a good idea to just blindly hope that your class is instantiated with a pointer type or a type that can have a null state - instead expect the type itself and transform it within the class.
Last edited on
By the way: it's generally not a good idea to just blindly hope that your class is instantiated with a pointer type or a type that can have a null state - instead expect the type itself and transform it within the class.



I don't understand what you mean. Can you give me an example so I can figure it out. Thanks.


Last edited on
This function only works with a nullable type:
1
2
3
4
5
template<typename T>
T returnNull()
{
    return nullptr;
}
This function works for any type, even void:
1
2
3
4
5
template<typename T>
T *returnNull()
{
    return nullptr;
}
I see. But expect one or the other this is still "expect ".
In the case I posted above it is a message map that route the message to the proper window/dialog proc and Windows defines them as below...

1
2
typedef INT_PTR (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);
typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);


So I'm "expecting" DLGPROC or WNDPROC. In fact it's not true because I've defined my own window proc and by the way this class is only used in another class in a "has-a" relationship. That's another story.

To go back to the main subject, as you posted in your code that imply the vector class, I see it all the time and from all I've read, the overhead seem very low (or almost null) compared to C-array. And in your code I could remove the index_ because I think that the vector keep all that is needed to parse the array (size method). In fact I didn't verify what it would look like using it with the find method but I'll see.

Anyway, thank guys for your input.

Topic archived. No new replies allowed.