0

I'm trying to make a program that deals with images, in which I have an image object and an image_view object that references a rectangle region in the image:

class image_view;

class image
{
    public:
        image(int width, int height);

        operator image_view() const;

    private:
        int m_width;
        int m_height;
        std::vector<pixel> m_pixels;
};

class image_view
{
    public:
        image_view(const image& ref, point origin, int width, int height);
        image_view(image_view view, point origin, int width, int height);

    private:
        const image& m_ref;
        point m_origin;
        int m_width;
        int m_height;
};

However, when I tried to copy an image_view, the compiler told me that the operator= member function had been deleted because of the non-static member reference. I naively tried to make my own member function with m_ref = other.m_ref but it didn't work since m_ref is const.

I considered using a smart pointer instead of a reference, but I didn't find a way of making a smart pointer to an already existing object.

One solution I found is the following:

image_view& image_view::operator= (const image_view& other)
{
    *this = image_view(other);
    return *this;
}

This compiles, but is it a good idea? (I might be wrong, but I feel bad about assigning stuff to *this.) If I do that, does that mean I have to define a destructor (even though I'm not allocating anything), move constructor and move assignment operator to satisfy the rule of 5?

J. Smith
  • 37
  • 1
  • 5
  • 1
    Using references as members is almost always a bad idea. Use a pointer. –  Mar 28 '18 at 17:20
  • Try running that `operator=` your created. You *will* get a stack overflow. – Justin Mar 28 '18 at 17:27
  • Related: https://stackoverflow.com/q/957087/1896169 , https://stackoverflow.com/q/892133/1896169 – Justin Mar 28 '18 at 17:28
  • Set image as a smart pointer, then have inside image_view a smart pointer member to it. – AdvSphere Mar 28 '18 at 17:58
  • I tried to run it, and it worked as expected (I'm using gcc 7.3.0 with `-std=c++17`). Neil Butterworth: do you mean a raw pointer? Isn't that bad? – J. Smith Mar 28 '18 at 18:43
  • @NeilButterworth Can you explain why references as members are bad? And why pointers as members better? – GrahamS Mar 28 '18 at 19:24

1 Answers1

0

If you want to express a non-owning, non-null wrapper that rebinds on assignment, the easiest way to do that is to use std::reference_wrapper:

class image_view
{
public:
    image_view(const image& ref, point origin, int width, int height);
    image_view(image_view view, point origin, int width, int height);

private:
    std::reference_wrapper<image const> m_ref;
    point m_origin;
    int m_width;
    int m_height;
};

The default copy constructor and assignment operator will do the right thing.

Barry
  • 286,269
  • 29
  • 621
  • 977