Pass reference to function that takes `std::unique_ptr` - c++

I have a reference to my object of type MyType, but I need to call a function, say myFunction that takes a std::unique_ptr<MyType>. What is the correct way to call myFunction? My attempt below seems to cause an "invalid pointer" error:
#include <memory>
class MyType {};
MyType myGlobalObj;
MyType& myGetter () {
return myGlobalObj;
}
void myFunction (std::unique_ptr<MyType> ptr) {
// Do important stuff
}
int main () {
MyType& myObj = myGetter();
std::unique_ptr<MyType> myPtr;
myPtr.reset(&myObj);
myFunction(std::move(myPtr)); // This causes "invalid pointer" at run time.
myPtr.release();
return 0;
}

What you are trying to do is not possible without either doing a (deep-)copy of myGlobalObj or modifying myFunction.
A std::unique_ptr takes ownership of the memory that is used to store the contained object. That means that the std::unique_ptr may free (or reallocate, or whatever) the memory that it 'owns'. What it would do in your case: As soon as the ptr variable goes out of scope at the end of myFunction, it will attempt to free the memory that it points to. Since myGlobalObj is a global variable, its memory may never be freed (before a controlled shutdown of your program…)
Thus, you should not ever wrestle a global object into a std::unique_ptr (or a std::shared_ptr, for that matter). If there is really no way of refactoring that method to take anything else than a std::unique_ptr, you must make a copy (on the heap!) of myGlobalObj, wrap that into a std::unique_ptr, and pass it to myFunction. Keep in mind that this way, myFunction loses the ability to modify myGlobalObj.

Related

Is there a way to detect if object instance is deleted (in lambda)?

I have this small template function to store my callback function for later "callback".
std::function<void(std::string)> stored_callback;
template<class ReadFileCallback, typename Object, class ...T>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback, Object* object, T ...params) {
std::cout << "fileMgr_ReadWithCallback is processing file: " << filename << std::endl;
stored_callback= [=](std::string s) {
(object->*callback)(s, params...);
};
}
void calledLater() {
stored_callback("somestring");
}
I'm using it from a class like this:
void MyClass::Read() {
fileMgr_ReadWithCallback("myfile", &MyClass::ReadResult, this, fileId);
}
This works nicely, but I have a terrible fear that it can cause a real mess if object gets invalidated (goes out of scope).
As MyClass can be put onto heap:
MyClass* c=new MyClass();
c->Read(); // callback stored
delete c; // c invalidated
calledLater(); // ???
If I try running this, it does not cause any error. But if something overwrites c's former space, it would cause a terrible UB. Or I'm mistaken?
Is there any way when c is deleted for either of these:
not call the stored_callback, or
not call (object->*callback)(s, params...);
Is this good for storing a weak_ptr?
stored_callback = [=](std::string s) {
std::weak_ptr<Object> obj = object; //or std::make_shared?
if (auto spt = obj.lock()) (spt->*callback)(s, params...);
};
Is there a way to detect if object instance is deleted
Yes, so long as you manage its lifetime with shared_ptr, and optionally track it with weak_ptr when you don't want to extend that lifetime.
There is no general way to do this for "unmanaged" objects, meaning those allocated and managed directly via raw pointers, or locals with automatic scope.
You can't detect whether the object still exists via a raw pointer, because if it was deleted or went out of scope, dereferencing the pointer is illegal in the first place. So, you must either
write your code to not destroy the object while the raw pointer exists (ie, static correctness)
not use raw pointers and instead use a smart pointer (most likely shared_ptr and weak_ptr) to control the object's lifetime
have the object somehow detach itself from callbacks when it is destroyed (which is intrusive, as now each object that could be used in a callback needs to know about it)

Can smart pointers be implicitly used as pointers?

Are smart pointers considered as pointers? And thus can they implicitly used as pointers?
Let's say I have the following class:
class MyClass {
//...
std::shared_ptr<AnotherClass> foo() { /*whatever*/ };
void bar(AnotherClass* a) { /*whatever too*/ };
//...
}
Then can I use MyClass the following way?
// m is an instance of MyClass
m.bar(m.foo());
No they can't be used interchangable. You would get a compiler error in your example. But you can always get the raw pointer by shared_ptr::get().
NO! It would be a terrible API. Yes, you could easily implement it within shared_ptr, but just because you could doesn't mean you should.
Why is it such a bad idea? The plain-pointer-based interface of bar doesn't retain an instance of the shared pointer. If bar happens to store the raw pointer somewhere and then exit, there's nothing that guarantees that the pointer it had stored won't become dangling in the future. The only way to guarantee that would be to retain an instance of the shared pointer, not the raw pointer (that's the whole point of shared_ptr!).
It gets worse: the following code is undefined behavior if foo() returns a pointer instance that had only one reference when foo() returned (e.g. if foo is a simple factory of new objects):
AnotherClass *ptr = m.foo().get();
// The shared_ptr instance returned by foo() is destroyed at this point
m.bar(ptr); // undefined behavior: ptr is likely a dangling pointer here
Here are the options; consider those listed earlier first before considering their successors.
If bar(AnotherClass *) is an external API, then you need to wrap it in a safe way, i.e. the code that would have called Original::bar should be calling MyWrapped::bar, and the wrapper should do whatever lifetime management is necessary. Suppose that there is startUsing(AnotherClass *) and finishUsing(AnotherClass *), and the code expects the pointer to remain valid between startUsing and finishUsing. Your wrapper would be:
class WithUsing {
std::unique_ptr<AnotherClass> owner; /* or shared_ptr if the ownership is shared */
std::shared_ptr<User> user;
public:
WithUsing(std::unique_ptr<AnotherClass> owner, std::Shared_ptr<User> user) :
owner(std::move(owner)), user(std::move(user)) {
user.startUsing(owner.get());
}
void bar() const {
user.bar(owner.get());
}
~WithUsing() {
user.finishUsing(owner.get());
}
};
You would then use WithUsing as a handle to the User object, and any uses would be done through that handle, ensuring the existence of the object.
If AnotherClass is copyable and is very cheap to copy (e.g. it consists of a pointer or two), then pass it by value:
void bar(AnotherClass)
If the implementation of bar doesn't need to change the value, it can be defined to take a const-value (the declaration can be without the const as it doesn't matter there):
void bar(const AnotherClass a) { ... }
If bar doesn't store a pointer, then don't pass it a pointer: pass a const reference by default, or a non-const reference if necessary.
void bar(const AnotherClass &a);
void bar_modifies(AnotherClass &a);
If it makes sense to invoke bar with "no object" (a.k.a. "null"), then:
If passing AnotherClass by value is OK, then use std::optional:
void bar(std::optional<AnotherClass> a);
Otherwise, if AnotherClass takes ownership, passing unique_ptr works fine since it can be null.
Otherwise, passing shared_ptr works fine since it can be null.
If foo() creates a new object (vs. returning an object that exists already), it should be returning unique_ptr anyway, not a shared_ptr. Factory functions should be returning unique pointers: that's idiomatic C++. Doing otherwise is confusing, since returning a shared_ptr is meant to express existing shared ownership.
std::unique_ptr<AnotherClass> foo();
If bar should take ownership of the value, then it should be accepting a unique pointer - that's the idiom for "I'm taking over managing the lifetime of that object":
void bar(std::unique_ptr<const AnotherClass> a);
void bar_modifies(std::unique_ptr<AnotherClass> a);
If bar should retain shared ownership, then it should be taking shared_ptr, and you will be immediately converting the unique_ptr returned from foo() to a shared one:
struct MyClass {
std::unique_ptr<AnotherClass> foo();
void bar(std::shared_ptr<const AnotherClass> a);
void bar_modifies(std::shared_ptr<AnotherClass> a);
};
void test() {
MyClass m;
std::shared_ptr<AnotherClass> p{foo()};
m.bar(p);
}
shared_ptr(const Type) and shared_ptr(Type) will share the ownership,
they provide a constant view and a modifiable view of the object, respectively. shared_ptr<Foo> is also convertible to shared_ptr<const Foo> (but not the other way round, you'd use const_pointer_cast for that (with caution). You should always default to accessing objects as constants, and only working with non-constant types when there's an explicit need for it.
If a method doesn't modify something, make it self-document that fact by having it accept a reference/pointer to const something instead.
Smart pointers are used to make sure that an object is deleted if it is no longer used (referenced).
Smart pointer are there to manage lifetime of the pointer they own/share.
You can think of a wrapper that has a pointer inside. So the answer is no. However you can access to the pointer they own via get() method.
Please note that it is not so difficult to make dangling pointers if you use get method, so if you use it be extra cautious.

Return object with 2 optional ctors in function

I have function in c++ with 2 optional c'tor of an object I've built (one with something in vector "vals" and other without).
...
RecievedMessage a(sc, type);
if (!vals.empty()){
//a.~RecievedMessage();
RecievedMessage a(sc, type, vals);
}
return &a;
}
the line in // is optional.
Would it work (with or without the optional line)? Why? If no, how to fix it without setter for "vals"?
thanks a lot.
No, it wouldn't work.
RecievedMessage a(sc, type);
// Here we construct 'a'
if (!vals.empty()){
//a.~RecievedMessage();
// If we enable this line, we destroy 'a'
RecievedMessage a(sc, type, vals);
// Here we construct a second 'a' that only exists in this block
}
// End of block: The inner 'a' is destroyed here automatically
return &a;
}
// End of block: The outer 'a' is destroyed here, again.
Destroying an object twice has undefined behavior. You don't want that.
If you don't call the destructor manually, the outer a is only destroyed once, which is good.
But in either case, RecievedMessage a(sc, type, vals); has nothing to do with the outer a and merely creates another variable.
There would be ways to work around that, but the final line of your code makes it all pointless:
return &a;
You're returning the address of a local variable. This is broken in and of itself: When the function returns, all of its local variables are destroyed automatically, so what you're returning is an invalid pointer.
Your code is all over the place, but what I think you're looking for is something like this:
ReceivedMessage *MakeReceivedMessage (foo sc, bar type, vector<whatever>& vals)
{
if (vals.empty())
return new ReceivedMessage (sc, type);
return new ReceivedMessage (sc, type, vals);
}
Of course, it would be better in this example to just have a single constructor and have the object test whether vals is empty when appropriate, but, in general, you can call whatever constructor you like whenever you like. Just manage your object lifetimes properly (and don't - ever - return a pointer to an object on the stack).
Example usage (to manage the lifetime of the object returned properly):
std::unique_ptr<ReceivedMessage> MyReceivedMessage (MakeReceivedMessage (...));
MyReceivedMessage->DoFunkyStuffWithMessage ();
....
Or, as melpomene points out, you can return a std::unique_ptr<ReceivedMessage> in the first place. Some (many?) would prefer that. You can construct it with std::make_unique.
There are three main issues with your code right now:
First of all, your commented out call to the destructor ~ReceivedMessage() should not be there at all. In C++, the destructor of objects is automatically called when an object's lifetime ends (either when it goes out of scope, or when delete is called if it was dynamically allocated with new). While there are some situations where explicitly calling a destructor is necessary ("placement new" for example), these are situations you're very unlikely to come across.
Secondly, your RecievedMessage a(sc, type, vals); declaration in the inner if does not replace the value of a in the outer scope. This just creates another variable of the same name which shadows the outer a, while return &a; in the outer scope can only refer to the outer a. The inner a no longer exists at this point as it has gone out of scope.
A way to fix this issue is to instead assign a new value to a by using the = operator and constructing a temporary ReceivedMessage:
if (!vals.empty()) {
a = ReceivedMessage(sc, type, vals);
}
This should work as long as a correct operator= is defined (implicitly or otherwise) for ReceivedMessage.
Thirdly, your function is returning a pointer to the local variable a. Since objects in C++ are destroyed as soon as they go out of scope, a no longer exists by the time the function has returned, so the ReceivedMessage * pointer the calling code obtains is invalid and it would be undefined behaviour to dereference that pointer and make use of it.
There are a couple of fixes to this issue:
The first option is instead of returning a pointer (ReceivedMessage *), just return a ReceivedMessage by value.
ReceivedMessage foo()
{
ReceivedMessage a(123);
return a;
}
This should work as long as a correct copy or move constructor is defined (implicitly or otherwise) for ReceivedMessage.
The second option is to make use of std::unique_ptr, and make your function instead return std::unique_ptr<ReceivedMessage>.
#include <memory>
std::unique_ptr<ReceivedMessage> foo()
{
std::unique_ptr<ReceivedMessage> a;
if (vals.empty()) {
a = std::make_unique<ReceivedMessage>(sc, type);
} else {
a = std::make_unique<ReceivedMessage>(sc, type, vals);
}
return a;
}
The advantage to this approach is that unique_ptr is nullable, so you can create a null unique_ptr without having to construct a ReceivedMessage straight away. Additionally, you can move and assign unique_ptr values safely without having a correct operator= or a correct copy / move constructor defined.
The calling code may look like this, when using unique_ptr:
std::unique_ptr<ReceivedMessage> message = foo();
foo->bar();
as opposed to the following when using ReceivedMessage directly:
ReceivedMessage message = foo();
foo.bar();

How to pass unique_ptr<T> in place of a raw *output* pointer parameter?

I have a pre-existing function in an external library, which looks like this;
bool CreateTheThing(MyThing *& pOut);
In short; I give it a raw pointer (by reference), and the function allocates memory and assigns my pointer to the newly-allocated object. When the function returns, it is my responsibility to free the memory, when I'm done.
Obviously, I'd like to store this result into a unique_ptr<MyThing>, and avoid the manual delete.
I could create a temporary raw pointer to use with the API call, and pass it into the constructor for the unique_ptr;
MyThing* tempPtr;
CreateTheThing(tempPtr);
unique_ptr<MyThing> realPtr = unique_ptr<MyThing>(tempPtr);
Is there a more direct method than this? One which doesn't require a temporary raw pointer? Ideally, there would be a method of unique_ptr which exposes its internal pointer in a way that could work directly with the CreateTheThing method?
unique_ptr<T>::get() does not allow this, to my knowledge. The pointer it returns is not a reference to the internally-used pointer.
You can save one line of code (potentially many times) by writing many lines of code once:
class Wrapper
{
std::unique_ptr<MyThing> &u;
MyThing *p;
public:
Wrapper(std::unique_ptr<MyThing> &u) : u(u), p() {}
operator MyThing* & ()
{ return p; }
~Wrapper()
{ u.reset(p); }
};
Usage:
std::unique_ptr<MyThing> u;
CreateTheThing(Wrapper(u));
Is there a more direct method than this? One which doesn't require a temporary raw pointer?
No, there isn't.
Ideally, there would be a method of unique_ptr which exposes its internal pointer in a way that could work directly with the CreateTheThing method? unique_ptr::get() does not allow this, to my knowledge.
Your knowledge is correct. That would defeat the whole purpose of the std::unique_ptr, therefore unique_ptr::get() is a const function and the pointer is returned by value.
However similar as your constructor example, you can always use std::unique_ptr::reset() to pass an externally allocated pointer.
Also note: If the 3rd party API requires you to release the memory using free() you may need to provide a special deleter function for the std::unique_ptr.
If you use the function often you could put the conversion in a function.
Best would be to change the API, but this can also work.
inline std::unique_ptr<MyThing> CreateTheThing()
{
MyThing* p;
if (CreateTheThing(p))
{
return std::unique_ptr<MyThing>(p);
}
return std::unique_ptr<MyThing>();
}
You could also make this overload to make refactoring even easier:
inline bool CreateTheThing(std::unique_ptr<MyThing>& ptr)
{
try
{
MyThing* p;
if (CreateTheThing(p))
ptr = std::unique_ptr<MyThing>(p);
else
return false;
}
catch (std::bad_alloc&)
{
return false;
}
return true;
}

How to declare a variable that stores an object returned by reference?

C++ references are still confusing to me. Suppose I have a function/method which creates an object of type Foo and returns it by reference. (I assume that if I want to return the object, it cannot be a local variable allocated on the stack, so I must allocate it on the heap with new):
Foo& makeFoo() {
...
Foo* f = new Foo;
...
return *f;
}
When I want to store the object created in a local variable of another function, should the type be Foo
void useFoo() {
Foo f = makeFoo();
f.doSomething();
}
or Foo&?
void useFoo() {
Foo& f = makeFoo();
f.doSomething();
}
Since both is correct syntax: Is there a significant difference between the two variants?
Yes, the first one will make a copy of the returned reference, while the second will be a reference to the return of makeFoo.
Note that using the first version will result in a memory leak (most likely), unless you do some dark magic inside the copy constructor.
Well, the second will result in a leak as well unless you call delete &f;.
Bottom line: don't. Just follow the crowd and return by value. Or a smart pointer.
Your first code does a lot of work:
void useFoo() {
Foo f = makeFoo(); // line 2
f.doSomething();
}
Thinking of line 2, some interesting things happen. First, the compiler will emit code to construct a Foo object at f using the default constructor of the class. Then, it will call makeFoo(), which also creates a new Foo object and returns a reference to that object. The compiler will also have to emit code that copies the temporary return value of makeFoo() into the object at f, and then it will destroy the temporary object. Once line 2 is done, f.doSomething() is called. But just before useFoo() returns, we destroy the object at f, as well, since it is going out of scope.
Your second code example is much more efficient, but it's actually probably wrong:
void useFoo() {
Foo& f = makeFoo(); // line 2
f.doSomething();
}
Thinking of line 2 in that example, we realize that we don't create an object for f since it is just a reference. The makeFoo() function returns an object that it has newly allocated, and we keep a reference to it. We call doSomething() through that reference. But when the useFoo() function returns, we don't ever destroy the new object that makeFoo() created for us and it leaks.
There's a few different ways to fix this. You could just use the reference mechanism you have in your first code fragment, if you don't mind the extra constructors, creation, copying and destruction. (If you have trivial constructors and destructors, and not much (or none) state to copy, then it doesn't matter much.) You could just return a pointer, which has the strong implication that the caller is responsible for managing the life cycle of the referenced object.
If you return a pointer, you've implied that the caller must manage the life cycle of the object, but you haven't enforced it. Someone, someday, somewhere will get it wrong. So you might consider making a wrapper class that manages the reference and provides accessors to encapsulate the management of the objects. (You could even bake that into the Foo class itself, if you wanted to.) A wrapper class of this type is called a "smart pointer" in its generic form. If you're using the STL, you'll find a smart pointer implementation in the std::unique_ptr template class.
A function should never return a reference to a new object that gets created. When you are making a new value, you should return a value or a pointer. Returning a value is almost always preferred, since almost any compiler will use RVO/NRVO to get rid of the extra copy.
Returning a value:
Foo makeFoo(){
Foo f;
// do something
return f;
}
// Using it
Foo f = makeFoo();
Returning a pointer:
Foo* makeFoo(){
std::unique_ptr<Foo> p(new Foo()); // use a smart pointer for exception-safety
// do something
return p.release();
}
// Using it
Foo* foo1 = makeFoo(); // Can do this
std::unique_ptr<Foo> foo2(makeFoo()); // This is better