Which is a better way - store `const reference` vs `boost::shared_ptr<Class>` as a member variable

StackOverflow https://stackoverflow.com/questions/23523255

  •  17-07-2023
  •  | 
  •  

Question

class ClassOne : boost::noncopyable
{
};

class ClassTwo : boost::noncopyable
{
public:
    ClassTwo(const ClassOne& one)
        : m_one ( one ) {}

private:
    const ClassOne& m_one;
};

class ClassThree : private boost::noncopyable
{
public:
    ClassThree(boost::shared_ptr<const ClassOne> one)
        : m_one ( one ) {}

private:
    boost::shared_ptr<const ClassOne> m_one;
};

class ClassFour : private boost::noncopyable
{
public:
    ClassFour(const boost::shared_ptr<const ClassOne>& one)
        : m_one ( one ) {}

private:
    boost::shared_ptr<const ClassOne> m_one;
};

Question> During codereview, I was told that the code (similar as ClassTwo) should be replaced by the code (similar as ClassThree) because storing a const reference to outside class is NOT safe.

Is that true?

Thank you

Was it helpful?

Solution

Const reference and shared_ptr models two similar, but different concepts.

If you have a const reference, you "know" something, you can inspect this thing (through const methods) but you can't change this thing, and even more important, this thing might vanish any time: you don't own it.

On the other hand, shared_ptr models a shared ownership. You own the object pointed by the pointer. You can change it and it wont be destructed, unless every owner gets destructed.

Returning const reference to a private member is safe; accepting such a reference is a different thing. You have to make sure the reference remains valid.

shared_ptr is easier to handle but it's a more expensive solution.

Regarding the exact dynamics, read the manual of shared_ptr

OTHER TIPS

I think erenon has a good writeup.

I'd like to add a little from the pragmatic angle:

  • const reference members make classes non-copyable (in fact, they could be copyable, but generation of default special members is inhibited (except for the destructor)

  • shared_ptr, on the other hand, make stuff inherently copyable (with shallow-clone semantics). This turns out to be really useful in functors where state will be kept/passed along. Boost Asio is a prime example, because logical threads of execution meander across threads and the lifetime is largely unpredictable.

  • I suggest using a shared_ptr<const T>; This adds immutability in the context of sharing. You will need to clone the object pointed to replace it with a changed version, and the shared object will not be modified through the shared_ptr<const T>

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top