Mr. Developerdude
Mr. Developerdude

Reputation: 9678

What is best pointer/reference type when returning member possibly allocated on the stack in C++?

So to illustrate my question I have made an example:

#include <iostream>

using namespace std;


struct A
{
  void doSomething (){
      cout << "Something\n";
  }
};


struct B
{
  A a;

  A *getA ()
  {
    return &a;
  }
};


int
main ()
{

  B *b = new B ();
  A *a = b->getA ();


  // POINT 1
  if (nullptr != a)
    {
      a->doSomething ();
    }

  delete b;
  b = nullptr;

  // POINT 2
  if (nullptr != a)
    {
      a->doSomething ();
    }

  return 0;
}

This compiles and runs without errors on my machine, but if you inspect the code, really there is a problem of a dangling pointer on the lines following the comment marked "POINT 2".

Since b was deleted, then a is now invalid (since it was deleted by dtor of b).

So I could use a shared pointer to remedy this, but that would keep the instance of a around even after b was deleted, and also I would not be able to allocate a on the stack. These are two things I want to avoid. Instead I simply want to know if a is still valid.

I could also have used a unique pointer but then I could only have one single instance of a which is not what I want either, I want many copies of the pointer to a.

So is there some existing pointer/reference type that would allow me to do this? Are there any reason why this is a good/bad idea?

Upvotes: 2

Views: 48

Answers (3)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385264

The best way is to not expose a.

Your B is the interface. Give it the functions you need to perform. Have it go on to invoke whatever it needs to invoke on the a in order to make that happen.

Then remove getA(), and make a private.

Now it's completely encapsulated and the calling scope cannot arse around with it like this!

No need for pointers or dynamic allocation; just good, old-fashioned OOP.

Upvotes: 1

Acorn
Acorn

Reputation: 26146

You have just discovered the wonders of ownership semantics :)

How to solve this problem depends on the design of your application: what you need and what you are trying to achieve.

In this case, if you really want to share ownership of an object, use std::shared_ptr which keeps a reference count of how many pointers are left, so that the last deletes the object; possibly std::weak_ptr if you only need to check if the object is still alive but don't want to keep it alive longer than needed.

However, do note that (ab)using shared pointers may be a sign of a bad design.


By the way, your A a; member is not allocated in the stack (i.e. the title is wrong).

Upvotes: 3

Slava
Slava

Reputation: 44268

Only viable solution using standard library that come in mind is to use std::weak_ptr() - it will allow to check object validity without holding it's ownership. That comes with price - you have to maintain ownership of it with std::shared_ptr. Though it is possible to create std::shared_ptr to an object with automatic storage duration and noop deleter I would do that only if I really need that as such method is error prone and defeats the purpose of a smart pointer.

Upvotes: 3

Related Questions