Pass pointer to auto_ptr with C++ - c++

i have a function that does this:
static MyClass* MyFunction(myparams)
{
return new MyClass(myparams)
}
and i would be able to call this function inside another one that has the following signature:
void MyFunction2(std::auto_ptr<MyClass> myparam)
but when I try to do it i have a compiler error:
Impossible to convert the first param
from MyClass * to std::auto_ptr<_Ty>
why? Thank you for any help
EDIT 1
As asked the myparams types are normal but there is also a T param because the function is inside a template class

std::auto_ptr<> has an explicit constructor, like any other smart pointer. That means that there is no implicit conversion from T* to std::auto_ptr<T> to prevent from accidentally deleting an object. Hence you need to convert your raw pointed to std::auto_ptr<> explicitly:
MyFunction2(std::auto_ptr<MyClass>(MyFunction()));
It is also a good idea to make your factory functions return a smart pointer instead of a raw pointer, it makes it clear to the reader that the ownership of an object is being transferred to the caller:
static std::auto_ptr<MyClass> MyFunction(myparams)
{
return std::auto_ptr<MyClass>(new MyClass(myparams));
}

There's no implicit conversion from a raw pointer to an auto_ptr. Just explicitly call it out:
MyFunction2(std::auto_ptr(MyFunction(params)));
Note that the allocated memoty will be destroyed after the call to MyFunction2 because the temporary auto_ptr will be gone, deallocating it.

You might want to call the MyFunction2 function like this...
void f() {
MyClass* directptr = MyFunction(myparams);
std::auto_ptr<MyClass> p(directptr);
MyFunction2(p);
cout << p.get() << endl; // Prints NULL!
}
However, when MyFunction2 ends the MyClass instance will be deleted, and upon returing p will be NULL and directptr will point to a deleted object.

Related

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.

How to prevent deletion of a raw pointer that is used as shared pointer?

I implemented a C-API for a C++ class which uses shared-pointers of other objects to access them.
In my C-API I can of course only get raw pointers.
So I "convert" the raw pointer in my C-API to a shared-pointer and use this then with my C++ class methods:
method(std::shared_ptr<dataType>(raw-pointer));
Now I have the problem that at the end of "method" always the shared-pointer destructor is called and it unfortunately kills the object my raw-pointer is pointing at (which I don't want).
So, how can I prevent the raw-pointer from being killed?
I already tried shared-pointer functions like reset() or swap(), but they all didn't let my raw-pointer go...
bool Traffic_doStep(traffic_handle t, environment_handle e, double cycletime) {
if (!valid(t, __FUNCTION__)) return false;
if (!valid(e, __FUNCTION__)) return false;
if (!valid(cycletime, __FUNCTION__)) return false;
try {
t->doStep(std::shared_ptr<Environment>(e), cycletime);
return true;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return false;
}
}
Expected result would be that the raw-pointer e is still pointing to a valid object after this function returned.
Actually the raw-pointer points then to a deleted object.
Don't put the pointer in a std::shared_ptr
The purpose of Smart Pointers in C++ is to provide automatic Lifetime management. When you write std::shared_ptr<int> ptr{raw_ptr};, the expectation is that when ptr goes out of scope, the object pointed to by raw_ptr will be delete'd. If this is not the intent, then you should not be placing the pointer in a smart pointer.
So if your application does not manage the lifetime of a pointer, then it is perfectly acceptable to store a raw pointer.
If the API behind the function cannot be altered, you will instead need to construct the std::shared_ptr with a no-op deleter function, so that when clean-up is called, nothing will happen to the pointer.
try {
std::shared_ptr<Environment> temp_ptr{e, [](int *) {}/*No-Op Deleter*/};
t->doStep(temp_ptr, cycletime);
return true;
}
This will solve your problem, but this is, of course, an Antipattern; don't do this unless you've been forced to by API design constraints that you cannot control.
You may provide a custom deleter of a shared pointer.
Here is a viable constructor:
template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );
But I would rather use a unique pointer and then release it.

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 create a smartpointer to a class and initialize the class constructor

I have
p2t::CDT* cdt = new CDT(p2d);
where p2d is an object that is passed by reference to the CDT class constructor.
I want to replace this with a smartpointer:
std::unique_ptr< p2t::CDT> cdt(p2d);
but it doesn't work in the way I wrote.
What is the correct way of writing the smart pointer for it?
After creating the smart pointer, do I use the pointer like a normal pointer (ie. (*cdt) gives me the object it points to, right? ) ?
you should use
std::unique_ptr<p2t::CDT> cdt(new p2t::CDT());
there is some documentation about it.
http://en.cppreference.com/w/cpp/memory/unique_ptr
About your question:
After creating the smart pointer, do I use the pointer like a normal pointer (ie. (*cdt) gives me the object it points to, right? ) ?
Yes, *cdt gives you object that it points too, because smart pointers overloads * operator.
And no, you cant use it like regular pointer, its a template class instance, so giving it to function like void foo(p2t::CDT * ptr); wont work.
BUT! there is a member function get() that will return normal pointer, which is wrapped into unique_ptr object that you can use with a such function.
void bar(Foo * ptr)
{
// some operations with ptr
}
std::unique_ptr<Foo> cdt(new Foo());
bar(cdt.get()); // can do so
Also, smart pointers overloads -> operator, so you can call methods of some class just like with regular pointer.
class Foo{
public:
void bar();
};
std::unique_ptr<Foo> ptr(new Foo());
ptr->bar(); // it works!