0

I want to use smart pointers in this way:

using namespace std;

shared_ptr<string> foo;
weak_ptr<string> bar (foo);
foo = make_shared<string>("some string");
cout << *bar.lock(); // SIGSEGV

The clue is how to initialize shared_ptr's object manager without construction the object (string in this case). Is it even possible? I could use default ctor of the object and later use copy/move assignment. But may some more elegant solution exist?

It is worth for me that the object won't be initialized - it would be a lie in logic if I would initialize the shared_ptr with empty value.

saleph
  • 149
  • 11

2 Answers2

1

Why not do this instead:

shared_ptr<string> foo = make_shared<string>();
weak_ptr<string> bar (foo);
*foo = "some string":

That way you are actually sharing a string. What you described is more like sharing a shared pointer.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I know about this possibility :) But it is worth for me that the object won't be initialized - I use it in a large program and it will be perfect for me if I manage to create only object manager, but not the object. – saleph Feb 15 '16 at 16:30
  • @user3545806 hmm, so should I search solution with some nested pointers? I mean: `shared_ptr>` – saleph Feb 15 '16 at 16:43
  • I am sorry was answering other question. – VladimirS Feb 15 '16 at 16:48
  • @KerrekSB Ok, thanks. I'm thinking about some additional class for lazy initialization too. I'll check in code which solution will be the best and I post it. – saleph Feb 15 '16 at 18:30
0

I solved my problem. The core of this idea is to use nested pointers: shared_ptr<unique_ptr<MYTYPE>>. In my case I created a wrapping template:

template<typename T>
class LazyInitializator : public std::unique_ptr<T> {
public:
    LazyInitializator() : std::unique_ptr<T>() {} // this ctor offers lazy initialization
    LazyInitializator(const T& val) : std::unique_ptr<T> (std::make_unique<T>(val)) {} // for normal construction
    LazyInitializator& operator= (const T& val) { 
        if (!std::unique_ptr<T>::operator bool()) // if object wasn't constructed
            std::unique_ptr<T>::operator= (std::make_unique<T>(val)); // construct it
        **this = val; // use assingment op provided by T - no unneccessary mem allocation
        return *this;
    }
};

Thanks to it I can use shared_ptrs in easier way. I can do sth like this:

using namespace std;

shared_ptr<LazyInitializator<string>> foo = make_shared<LazyInitializator<string>>();
weak_ptr<LazyInitializator<string>> bar (foo);
*foo = "some string";
cout << **bar.lock();

Yes, I know, looks a bit tricky, but it is the best solution for me now.

saleph
  • 149
  • 11