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.
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
A Class-Key Must Be Declared When Declaring a Friend
Use Const Wherever Possible in C++
Why Isn't Operator Overloading for Pointers Allowed to Work
Potential Problem in "Swapping Values of Two Variables Without Using a Third Variable"
How Concatenate a String and a Const Char
Why Is It a Compile Error to Assign the Address of an Array to a Pointer "My_Pointer = &My_Array"
C++11 Thread Class How to Use a Class Member Function
How to Run Only One Instance of Application
Stl Ordering - Strict Weak Ordering
What Are the Advantages and Disadvantages of Implementing Classes in Header Files
Understanding How Lambda Closure Type Has Deleted Default Constructor
Why Does Adding 0 to the End of Float Literal Change How It Rounds (Possible Gcc Bug)
Element Count of an Array in C++
Creating and Deallocating a Qt Widget Object
What Does the & (Ampersand) at the End of Member Function Signature Mean