1

I have been thinking and searching this but I can't solve this question. I would like an object that when copied into another object, both objects share certain member variable. So, when I change the value of the member variable of object1, it's also changes the variable in object2. Example:

class ABC {
public:
    int a = 5;
    //...
}

int main() {
    ABC object1;

    ABC object2 = object1;

    object2.a = 7;      // now, object1.a is equal to 7
    object1.a = 10;     // now, object2.a is equal to 10
}

I know about copy constructors, but I am not sure if it applies here or there is a better method. I have been thinking about using pointers or references, but can't make the trick. Note that I don't want all the objects to share the same variable.

Anselmo GPP
  • 425
  • 2
  • 21
  • 1
    If your desire is for all objects of this class to share the same variable, you can make it static. If you only want those two to share a variable and that connection is communicated using the copy constructor or assignment operator, you can use a shared pointer variable. – DrPepperJo Jun 18 '18 at 20:53
  • In C++, sharing a reference to data between multiple instances would break copy semantics (if you use the copy constructor to share that data). That is, when you copy something, they should be completely disjoint so that changing one copy does not affect the other. This is important because the compiler understands copy semantics and uses that when optimizing your code. For more on this, you might want to check out some of Sean Parent's talks on YouTube. – Tim Johns Jun 18 '18 at 21:00
  • That being said, you might consider a factory function, such as `unique_ptr createShallowCopy(const ABC& itemToCopy)`, so that the reader knows that this isn't a proper copy, and the compiler won't treat this function like the copy constructor. – Tim Johns Jun 18 '18 at 21:04
  • @TimJohns this is wrong. Sharing a common reference among different objects in no way "breaks copy semantics" nor does it impede compiler optimizations. For instance if I want to share a `const large_data_structure&` that is same across like objects, this would be much faster as to avoid unnecessary copies of the stated object. – Joseph Franciscus Jun 19 '18 at 01:00
  • `That is, when you copy something, they should be completely disjoint so that changing one copy does not affect the other.` generally this is good practice but there are more than enough cases when doing otherwise is acceptable and even better. `This is important because the compiler understands copy semantics and uses that when optimizing your code.` Technically this is correct but ultimately misleading; sharing data (with references or pointers) will not reduce the ability of the compiler to optimize your code. – Joseph Franciscus Jun 19 '18 at 01:06
  • @JosephFranciscus Let me put it another way. There is the concept of value semantics (where assignment and copy make fully disjoint objects) and the concept of reference semantics (where assignment and copy make objects that refer to the same underlying piece of data. This question is asking how to make a type that, when used as a value type, will exhibit value semantics for some internal data and reference semantics for other internal data. This makes it very unclear (without detailed knowledge of the internal code) whether operating on one instance will affect another. – Tim Johns Jun 19 '18 at 13:57
  • @TimJohns 1) The comment on "breaking copy semantics" are not clear and would easily confuse a beginner. 2) The comment on compiler optimizations is not relevant and is completely misleading. 3) yes I know what copy semantics are, I've already commented that I agreed some of the things you mentioned are generally considered to be good practice. – Joseph Franciscus Jun 19 '18 at 21:11

1 Answers1

6

What you need is a pointer. The pointer points to the object and then all objects that copy the first one just copy the pointer so that they all point to the same thing. To make life easy we can use a std::shared_ptr to manage the allocation and deallocation for us. Something like:

#include <memory>

class Foo
{
private:
    std::shared_ptr<int> bar;
public:
    Foo() : bar(std::make_shared<int>()) {}
    int& getBar() { return *bar; }
};

int main()
{
    Foo a;
    a.getBar() = 7;
    Foo b = a;
    b.getBar() = 10;
    // now getBar returns 10 for both a and b
    Foo c;
    // a and b are both 10 and c is 0 since it wasn't a copy and is it's own instance
    b = c;
    // now b and c are both 0 and a is still 10
}
Anselmo GPP
  • 425
  • 2
  • 21
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Thank you, that was what I needed. Now I know where to look. That works fine. – Anselmo GPP Jun 18 '18 at 22:36
  • Bear in mind that the default assignment operator here will cause the destination to start sharing the source's `bar` and forget about its old shared object (as opposed to copying the value); if that is not the desired behaviour you will need to write an assignment operator – M.M Jun 19 '18 at 01:53