Search code examples
c++referencescopetemporary

References: am I going to go out of scope?


I am new to C++, and more used to Java and C#, and so I need your fine help, please.

I have this situation: I have an abstract class SS representing a way to construct a specific scheme. This scheme uses an inner class SSP, that is yet another abstract class. The reason is that I can have different implementations for SS and SSP, but I would like to have it as generic as possible.

Now, one possible implementation for SS is A, and the respective implementation for SSP is AP. So, I have something like

class SSP {
  // abstract class
}

class SS {
  // abstract class
  SSP & my_p; // since this is an abstract member, I need a reference or a pointer here
  ...

  SS(SSP & p):
    my_p(p)
  {}
  ...

}

class AP : public SSP {
  int my_a;
  int my_b;

  AP(int a, int b):
    my_a = a, my_b = b
  {...}
}

class A : public SS {
  ...
  A(int a, int b):
    SS( AP(a,b) )
  {}
}

Now, what bugs me about this code is the feeling that I'm going to get a reference that goes out of scope. When I create AP implicitly in the constructor of A, is that a temporary object that will be destroyed as soon as the constructor finishes? If that is the case, will then the value of my_p in A be undefined?

What is the best way to do this, using pointers and a specific new in the constructor, or is there a better way? I would like the reference my_p to last for as long as the instance of A itself lasts.

Incidentally, do I have to redeclare the variable SSP & my_p in class A, this time as AP?

Thanks all.


Solution

  • If you're using raw references/pointers, there is no way for your class to control the lifetime of the values passed in. Also note that by using a reference as a class member, you are mandating that an object of type 'SS', once constructed, can never have a different value for 'm_p'. I suggest using pointers instead of references.

    Now, the only way to absolutely guarantee that the lifetime of the member is by taking ownership of the value when it is supplied in the constructor. You can do this using raw pointers (and simple written contract), or more preferably, using a language feature such as smart pointers to enforce this contract. Either way, the allocation will need to have happened from an arena (heap, or some such, but not the stack) whose lifetime exceeds that of your containing object.

    Your code re-written using shared_ptr:

    #include <iostream>
    #include <memory>
    
    using namespace std;
        class SSP {
          // abstract class
        };
    
        class SS {
          // abstract class
          std::shared_ptr<SSP> my_p; // since this is an abstract member, I need a reference or a pointer here
          // ...
          public:
          SS(std::shared_ptr<SSP> p):
            my_p(p)
          {}
          // ...
    
        };
    
        class AP : public SSP {
          int my_a;
          int my_b;
          public:
          AP(int a, int b):
            my_a(a), my_b(b)
          {//...
          }
        };
    
        class A : public SS {
          // ...
          A(int a, int b):
            SS(std::make_shared<AP>(a,b))
          {}
        };
    
    int main() {
        // your code goes here
        return 0;
    }
    

    If your object is the sole owner of the pointer, you should consider using unique_ptr.