Search code examples
c++optimizationshared-ptrshared-memorymove-semantics

Sharing underlying state in C++


Hi I'm wondering if there is any C++ standard that allows the compiler to "share" the data with an object.

IE

LinkedList a = std::share(myLinkedListObject); 

In which case the data of a is identical to myLinkedListObject and they share the same reference to memory. In such instance the ownership of the data could either be handled by a shared_ptr or the original object (myLinkedListObj) would retain ownership and control the lifespan of the data.

I acknowledge that the intuitive response and solution would simply use a pointer to the appropriate object but I am creating a wrapper class for a set of data in which case the fields of the wrapper class be the different but the data itself be identical.


Solution

  • There is nothing built in to C++ that codifies the semantics you want, mostly because unlike move and copy - the full behavior of the source and destination objects aren't really well defined. For example, what if you modify the source object a after your "share" operation? Should the the source list also reflect your modification?

    If so, then you want some type of reference. Depending on the surrounding code and the ownership of the source object, you might be able to accomplish that with a plain reference or pointer, or you may need to use some type of smart pointer like a shared_ptr.

    If not, then you are really talking about a copy operation: the source is copied to the destination, but they have distinct states after that point. In this case sharing the underlying state is still possible, but any write operation to either object needs to modify only the written object. This is referred to as copy-on-write (COW) and can be used to implement certain operations in an efficient way without affecting copy semantics.

    You could implement copy-on-write semantics yourself depending on your use case. For example, if you have a linked list of immutable objects, a share operation could conceivably simply point at the original list, and any mutations would adjust only the necessary nodes to ensure that only the written list is logically modified.

    In your specific case, it isn't really clear which of these options you want (if either). You mention that you want to create a wrapper object around some data in which the fields of the wrapper object may be different but the underlying data will be the same. That itself doesn't require any tricks at all: you just have a wrapper object which has fields, and then the data field which is shared must be a pointer or reference1 to a data object with appropriate lifetime semantics (e.g., shared_ptr).


    1 In general, reference members are not too useful and pointers (dumb or smart) should generally be preferred.