Create Shared_Ptr to Stack Object

Create shared_ptr to stack object

Is it ever safe/possible/good to create a smart_ptr from a stack object?

Safe? Only if you can guarantee that the stack which created that object will only be ended after all shared_ptr's that pseudo-own it.

Possible? Sure: pass shared_ptr's constructor a deleter object that does nothing:

auto sptr = shared_ptr<Player>(&player, [](Player *) {});

When the last shared_ptr is destroyed, the deleter will be called and nothing will be deleted.

Good? Not really. As noted above, safety is not something that can be universally guaranteed in such code. Depending on your code structure, this may be legitimate. But it requires great care.

This SomeClass is expecting to claim ownership of a resource; that's why it's taking a shared_ptr. You're kind of lying to it by passing it a shared_ptr that doesn't really own the object it references. That means the onus is on you and your code structure to not violate the promise you made to SomeClass that it would have shared control over that object's lifetime.

c++ shared_ptr of stack object

how do I dictate that a parameter was not allocated on the stack?

Yes, require the caller to provide a std::shared_ptr<RenderModel>. If the caller misconstructs the std::shared_ptr, that's the caller's problem, not yours.

If you intend for a RenderView to be the sole owner of a particular RenderModel, consider having the function take a std::unique_ptr or std::auto_ptr instead; this way it is clear that the caller should not retain ownership of the object after it calls the function.

Alternatively, if RenderModel is cheap to copy, make a copy of it and use the copy:

_model.reset(new RenderModel(model));

Set shared_ptr to point existing object

There is not much point in using a shared_ptr for an automatically allocated object.

Technically you can do it, by giving the shared_ptr a deleter that doesn't do anything, and changing your vtx to be a vector of shared pointers to const vectors.

E.g. changing the declaration to

vector < shared_ptr <Vector3 const> > vtx;

and adding a pointer like this:

vtx.push_back( shared_ptr<Vector3 const>( &vt, [](Vector3 const*){} ) );

Disclaimer: untested code, not touched by a compiler.

However, unless you're going to also add pointers to vectors that need to be deleted, just use a vector of raw pointers. Or, just use a vector of vectors, and copy the in-data.


It's not a good idea to use raw pointers to hold ownership. For that use smart pointers.

But conversely, it's not a good idea to use ownership smart pointers to hold pure references to static or automatic objects. For that, use raw pointers or references.

In general. Sample Image

Create shared_ptr from reference

Though, your error stems from the fact that the std::shared_ptr<Author> constructor in use expects Author*, but the expression &t_author results to an object of type const Author*


Another wrong thing:

void Book::setAuthor(const Author& t_author)
{
m_author = std::shared_ptr<Author>(&t_author);
}

Imagine calling book.setAuthor(Author("Herb Sutter"));, you will have a dangling pointer because t_author will cease to exist after that function completes.


You need to copy or move the object into your std::shared_ptr instance. Use std::make_shared<T> to create your std::shared_ptr<T> objects whenever possible.

void Book::setAuthor(const Author& t_author)
{
m_author = std::make_shared<Author>(t_author);
}

Better still:

void Book::setAuthor(Author t_author)
{
m_author = std::make_shared<Author>(std::move(t_author));
}

Pointer to stack object without ownership

Raw pointers are perfectly fine here. C++11 doesn't have any other "dumb" smart pointer that deals with non-owning objects, so you cannot use C++11 smart pointers. There is a proposal for a "stupid" smart pointer for non-owned objects:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf

already implemented experimentally as std::experimental::observer_ptr (thanks @T.C. for the hint).

Another alternative is to use a smart pointer with a custom deleter that doesn't do anything:

#include <memory>

int main()
{
int a{42};

auto no_op = [](int*){};
std::unique_ptr<int, decltype(no_op)> up(&a, no_op);
}

or, as mentioned by @T.C. in the comment, a std::reference_wrapper.

As mentioned by @Lightness Races in Orbit, a std::weak_ptr may also be a solution, as the latter is also a non-owning smart pointer. However a std::weak_ptr can only be constructed from a std::shared_ptr or another std::weak_ptr. A serious downside is that the std::shared_ptr is a "heavy" object (because of the internal reference counting mechanism). Note that even in this case the std::shared_ptr must have a trivial custom deleter, otherwise it corrupts the stack for pointers to automatic variables.

How to move stack object into std::shared_pointer without instantiation

It can be done. No tricks needed. Just move the object:

shared_pointers_container.insert(std::make_shared<my_class>(getMyClassObject()));

// or if you need to start from `obj`:

my_class obj = getMyClassObject();
// work with obj
shared_pointers_container.insert(std::make_shared<my_class>(std::move(obj)););

On your remarks:

without actually instantiating the class?

(in case the constructor does some changes).

This is completely unreasonable. If the constructor doesn't do what it is supposed to do then the class is buggy.

To be more clear: the problem you are trying to solve is this: You have an object given by value from an external library. This object is move-only. You want to put this object into a container of shared pointers. This is the problem. In solving this problem you think you cannot use the move constructor but that is definitely not the case. The solution is to use the move constructor how I showed.

Move object from local variable to std::shared_ptr

How about

if (currentFooSetting) {
*currentFooSetting = f;
} else {
currentFooSetting = std::make_shared<Foo>(f);
}

this sort-of ensures that you have just one shared pointer, and once it is created, its value is changed on update. Alternately, if existing holders-of-the-shared-pointer should keep their values, just assign a new one:

currentFooSetting = std::make_shared<Foo>(f);

This will "fork" the views of current settings -- holders-of-a-shared-pointer keep the old one with old values, but functions that newly share the pointer get the new value.

Which makes more sense depends on your design (which is what Ted Lyngmo asks in a comment). Both code snippets assume your Foo class has suitable (copy) constructors.



Related Topics



Leave a reply



Submit