简体   繁体   中英

C++ Copy Constructor for array of pointers to objects

I have created a class that contains the size and an array of type Rectangle **a . is the initialization below correct:

C(int size = 1, Rectangle **a = new Rectangle *[1]);

For the copy constructor I've tried this which (edit: don't know how to complete to copy each pointer of the array into the copy, since each element is also a pointer):

C ( const C & other) : size{other.size},  a{size ? new Rectangle[size] : nullptr}
{
    // ....
}

Let the standard library do the work for you. Using std::vector<Rectangle> will be safer, simpler and more reliable.

To answer your question, no your copy constructor is not correct as it only creates a new array of the same size and doesn't copy the existing elements into it.

To avoid permanent brain damage, use std::vector<Rectangle> as a member.

class C {
public:
    C(const std::vector<Rectangle> &rectangles) : m_rectangles(rectangles) {}
    C(const C &other) : m_rectangles(other.m_rectangles) {}
private:
    std::vector<Rectangle> m_rectangles;
};

You need to respect the rule of 0/3/5 .

The rule of zero states:

Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership (which follows from the Single Responsibility Principle). Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators.

RAII containers are a good tool to avoid managing resources. This is the best scenario for you:

#include <vector>
struct Rectangle {};

class C
{
    std::vector<Rectangle> _v; // no memory management from C
public:
    size_t size() const { return _v.size(); }
    Rectangle      & operator()(size_t index)       { return _v[index]; }
    Rectangle const& operator()(size_t index) const { return _v[index]; }
};

If for some reason you need to manage your resources manually, the rules of 3 and 5 kick in.

In C++98, the rule of three states:

If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.

In C++11 and later, the rule of five replaces it:

Because the presence of a user-defined destructor, copy-constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator, any class for which move semantics are desirable, has to declare all five special member functions

struct Rectangle {};

struct C
{
    size_t      _size;
    Rectangle*  _data;

    C() : _size(0), _data(nullptr) {}
    C(size_t size) : _size(size), _data(_size == 0 ? nullptr : new Rectangle[_size]) {}
    C(C const& other) : _size(other._size), _data(_size == 0 ? nullptr : new Rectangle[_size])
    {
        std::copy(_data, other._data, other._data + _size);
    }
    C& operator=(C const& other)
    {
        C self = other; // copy construction
        using std::swap;
        swap(*this, self);
        return *this;
    }
    // if necessary: move constructor and move assignment operator
    ~C() { delete _data; }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM