简体   繁体   中英

Two objects of same class referencing each other

There are objects of the same type always occuring in pairs. They are never alone, they are never more than two, like entangled particles.

I would like to implement this problem in C++ with two instances of the same class referencing each other. Creating the primary instance automatically creates the secondary one:

#include <iostream>
using namespace std;

class Particle
{
    public:
    // Constructs primary instance
    Particle() :
    partner_(Particle(*this))
    {
        cout << "Hi, I'm primary." << endl;
    }

    private:
    // Constructs secondary instance
    Particle(Particle & partner) :
    partner_(partner)
    {
        cout << "Hi, I'm secondary." << endl;
    }

    Particle & partner_;
};

int main()
{
   Particle two_friends;

   return 0;
}

It doesn't compile:

main.cpp: In constructor ‘Particle::Particle()’:
main.cpp:10:14: error: cannot bind non-const lvalue reference of type ‘Particle&’ to an rvalue of type ‘Particle’
     partner_(Particle(*this))
              ^~~~~~~~~~~~~~~

Is there a way to resolve this using references or do I have to use pointers instead?

There is a huge problem in your system first particle created on the stack, it's livetime is ok, but what with second? In your code it created as temp variable and destroyed in constructor, so reference inside class is useless any way. What I think you should do is use std::pair on another wrapper and set partners by yourself, like

struct ParticlePair{
    Particle first;
    Particle second;
    ParticlePair()
    {
        first.setPartner( second );
        second.setPartner( first );
    }
}

Good idea to make Particle constructor private and declare ParticlePair as a friend, in this case you will unable to create Particles alone.

In case if you will try to use pointers there is another problem: how to delete properly? Deleting first should delete second, but it means that deleting second should also delete first. Sooner or later you will delete already deleted pointer or delete object created on a stack.

The reason it doesn't compile is that the compiler is saving you from making a mistake, you aren't allowed to pass a temporary object to a function (or constructor) as this is likely to cause bugs. In your case your temporary object would be destroyed at the end of your constructor and you'd only have one particle with a dangling reference to the now destroyed other object.

One solution would be to use shared and weak pointers (you need weak pointers or you'd have a circular reference).

#include <memory>

class Particle
{
public:
    static std::shared_ptr< Particle > create()
    {
        std::shared_ptr< Particle > first( new Particle() );
        std::shared_ptr< Particle > second( new Particle() );
        // first will own second
        first->partner = second;
        // second will have a weak pointer to first
        second->weakPartner = first;
        return first;
    }

    std::shared_ptr< Particle > getPartner()
    {
        if (partner)
        {
            return partner;
        }
        return weakPartner.lock();
    }

private:
    Particle() {};
    std::shared_ptr< Particle > partner;
    std::weak_ptr< Particle > weakPartner;
};

int main()
{
  std::shared_ptr< Particle > two_friends = Particle::create();
}

Keeping a shared_ptr to the first particle will keep the second alive but note that if you only have a shared_ptr to the second the first will be destroyed. You could avoid this by not using weak_ptr but then you would have to manually break the shared_ptr cycle before the particles would be destroyed.

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