Well I like to learn as much code as I can in a day and I just came across the copy constructor. I do not understand when I need to use it. Do I need to use it for every class I make?

I came across it after getting the error: 'class Bitmaps' has pointer data members but does not override 'Bitmaps(const Bitmaps&)' or 'operator=(const Bitmaps&)' [-Weffc++]

So I googled it as usual and came across the copy constructor and assignment vs. copy constructor.
Now after reading the documentation, it tells me that if I have a class already constructed, I can assign another class to it without the copy constructor. If the class is being initialized by another, I need a copy constructor.

Already assigned class:

class Point
{
   int x, y;

   public:
        Point(int X, int Y);
};

Point A(10, 10);
Point B(5, 5);

A = B; //Uses assignment operator?

Unassigned class:

class Point
{
       int x, y;

       public:
            Point(int X, int Y);
};

Point B(5, 5);

Point A = B;  //Copy constructor? This currently works fine for me without it :S

Now the code that gives me a problem is defined as so:

class Bitmaps
{
    private:
        PRGB Pixels;               //Pointer to a union.
        BITMAPINFO Info;           //This has to be initialized in member list with Constructor() : Info(0)?
        int width, height, size;
        BITMAPFILEHEADER bFileHeader;

    protected:
        HDC DC;
        HBITMAP Image;

    public:
        ~Bitmaps();                 //Deletes Pixels aka pointer. Deletes Image and releases DC.

        Bitmaps(const char* FilePath);
        Bitmaps(int Width, int Height, uint32_t BitsPerPixel = 32);

        PRGB GetPixels() {return Pixels}; //I believe this is what requires the copy con?
        HDC ReturnDC() {return DC;};
};



//My other class that gives the same error :S

class Pens
{
    private:
        HDC     hDC;
        HPEN    NewPen;
        HPEN    OldPen;

    public:
        Pens(HDC hdc, COLORREF colour);
        Pens(HDC hdc, DWORD Style, DWORD Width, COLORREF colour);
        ~Pens();

        void ColourPixel(Point ColourPoint);

        void DrawLine(Point Begin, Point End);

        void DrawRectangle(Box B);

        void DrawEllipse(Point UpperLeftBound, Point LowerRightBound);

        void DrawArcAngle(Point CenterPoint, DWORD Radius, float StartAngle, float EndAngle);

        void DrawArc(Point UpperLeftBound, Point LowerRightBound, Point ArcStartPoint, Point ArcEndPoint);

        void DrawArcTo(Point UpperLeftBound, Point LowerRightBound, Point ArcStartPoint, Point ArcEndPoint);
};

The only problem I can possibly see with my bitmap class is the GetPixels function which returns my internal pointer and that if the returned pointer is deleted, it can mess up my class when the constructor is called. Is a copy constructor going to fix this? Why do I need both the copy constructor and the assignment operator? Why the assignment operator do all the work like it's supposed to (copy my values to the other).

Does this mean I need more constructors for all my classes and two assignment overloads? Finally, do I need to check for self-assignment using if (this != ....)?

Recommended Answers

All 3 Replies

Most of your questions will find their answers in my tutorial on the subject. The tutorial involves C++0x / C++11 features (which is the new standard, not yet well-supported by compilers), you can just ignore those features.

The only problem I can possibly see with my bitmap class is the GetPixels function which returns my internal pointer and that if the returned pointer is deleted, it can mess up my class when the constructor is called. Is a copy constructor going to fix this?

No. Nothing will, for that specific issue. First of all, it must take a complete idiot programmer to go and delete a pointer that was delivered from an object (as in your bitmap class). The general idea is to avoid exposing an internal pointer like that. However, in situations like these (image class), it is often necessary to do so (unless you're a really clever programmer). The general understanding in this case is that anytime a pointer is delivered from an object (via a get-function), then that pointer is only valid for as long as the object is not changed in any way (via a mutator member function, that is, a non-const member function), and, obviously, nobody should call delete on that pointer. This is a pretty universal thing.

Why do I need both the copy constructor and the assignment operator?

Because they do different things. The copy-constructor creates an object by duplicating the content of another. The copy-assignment operator replaces the content of an object with a duplicate of the content of another. This is not the same thing, but they are closely related. Usually, you either don't need them (if all your data members are automatic (i.e., POD-types or RAII classes)), or you need to implement both, in which case you usually implement the copy-assignment operator using the copy-and-swap idiom.

For the other questions, again, read my tutorial.

commented: Indeed, a very complete tutorial. +3

Hey after reading the tutorial, I implemented this:

//Copy constructor
Bitmaps::Bitmaps(const Bitmaps& Bmp) : Pixels(((Bmp.width * Bmp.height) != nullptr) ? new RGB[Bmp.width * Bmp.height] : nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    memcpy(Pixels, Bmp.Pixels, Bmp.size);
    memcpy(Info, Bmp.Info, sizeof(Bmp.Info));
    memcpy(bFileHeader, Bmp.bFileHeader, sizeof(Bmp.bFileHeader));
}

//Move constructor.
Bitmaps::Bitmaps(Bitmaps&& Bmp) : Pixels(((Bmp.width * Bmp.height) != nullptr) ? new RGB[Bmp.width * Bmp.height] : nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    Bmp.Pixels = nullptr;
}

//Assignment operator
Bitmaps& Bitmaps::operator = (Bitmaps Bmp)
{
    Bmp.swap(*this);
    return *this;
}

//Swap no-throw?
void Bitmaps::swap(Bitmaps& Bmp) //throw()
{
    std::swap(Pixels, Bmp.Pixels);
    std::swap(Info, Bmp.Info);
    std::swap(width, Bmp.width);
    std::swap(height, Bmp.height);
    std::swap(size, Bmp.size);
    std::swap(bFileHeader, Bmp.bFileHeader);
}

It tells me that I need to intialize Info and bFileHeader in the member initialization list.. and I'm not sure if I did this all right :S I got the idea of the operator = and the swap but not the construction. I still do not understand why I need to use the using std::swap instead of just putting std::swap like I did above. I used the Nullptr instead of the 0.

I wasn't sure if to put the throw() infront of the swap or not as some forums say the no throw is better :S I also wasn't sure what to do with my HDC dc and HBitmap Image.

Anyone? This is my new copy constructor and move constructor as well as my non-throwing swap function. I'm skeptical on if I did it all correctly. I'm also not sure how to initalize BitmapInfo and bFileheader in the members initialization list :S Any help is appreciated.

//Copy Con:

Bitmaps::Bitmaps(const Bitmaps& Bmp) : Pixels(((Bmp.width * Bmp.height) != 0) ? new RGB[Bmp.width * Bmp.height] : nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    std::copy(Bmp.Pixels, Bmp.Pixels + (width * height), Pixels);
    Info = Bmp.Info;
    bFileHeader = Bmp.bFileHeader;
}

//Move Con:

Bitmaps::Bitmaps(Bitmaps&& Bmp) : Pixels(nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    this->Swap(Bmp);
    Bmp.Pixels = nullptr;
}

//Copy Assignment Operator:

Bitmaps& Bitmaps::operator = (Bitmaps Bmp)
{
    this->Swap(Bmp);
    return *this;
}

//Move Assignment Operator:

Bitmaps& Bitmaps::operator = (Bitmaps&& Bmp)
{
    this->Swap(Bmp);
    return *this;
}

//My swap function:

void Bitmaps::Swap(Bitmaps& Bmp) //throw()
{
    std::swap(Pixels, Bmp.Pixels);
    std::swap(Info, Bmp.Info);
    std::swap(width, Bmp.width);
    std::swap(height, Bmp.height);
    std::swap(size, Bmp.size);
    std::swap(bFileHeader, Bmp.bFileHeader);
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.