I encountered such code.
MyClass MyClass::get_information (const some_datastructure *record)
{
auto_ptr<MyClass > variable (new MyClass ());
variable ->set_article_id(record->article_id);
return *variable.get();
}
I understand this returns a (copy?) of object of type MyClass.
Initially, I thought it was returning auto_ptr object which didn't make sense to me (?)
since I thought auto_ptr object get destroyed when it goes out of scope.
Anyway, is the above code Ok? Does object *variable.get() exist when/after the function returns?
since it is returned by value, yes, the object is fine, although I don't understand the use of pointer or heap allocation for the matter...
Would be simpler with a regular variable:
MyClass var;
var.set_article_id(record->article_id);
return var;
Yes it does
Actually it creates a temporary rvalue of the underlying object of the pointer, in fact a copy. Notice that the return type is not MyClass* but MyClass. Thats why a copy is returned. *variable.get() also yields a rvalue.
Related
Could someone explain simply the reason why this does not work:
std::shared_pointer<Bar> getSharedPointer() {
return std::make_shared<Bar>();
}
...
auto foo = getSharedPointer().get();
Apparently using the raw pointer foo will cause a segfault because the lifetime of the shared pointer returned by getSharedPointer() will have run out. Somehow I would expect it to last until the end of its scope (like whatever block it is inside).
Is this correct and are there any analogous examples to this situation?
For getSharedPointer().get();, getSharedPointer() returns a temporary std::shared_ptr which will be destroyed after the expression immediately, and the pointer managed by it will be deleted too. After that foo will become dangled, any dereference on it causes UB.
auto foo = getSharedPointer().get();
// foo have become dangled from here
You could use a named variable instead:
auto spb = getSharedPointer();
auto foo = spb.get();
// It's fine to use foo now, but still need to note its lifetime
// because spb will be destroyed when get out of its scope
// and the pointer being managed will be deleted too
auto foo = getSharedPointer().get();
Whenever a function returns a type that is not a reference, the result of calling the function is an rvalue. Also, because the function getSharedPointer() returns a class type, the result is a temporary object.
The lifetime of that temporary object is defined as the end of the evaluation of the outermost expression, here getSharedPointer().get(). As soon as the foo variable is initialized, the owning smart pointer is destroyed; when the last shared_ptr owning that object is destroyed, the object is deleted.
Here getSharedPointer() always returns shared_ptr that doesn't share the managed object (use_count() is 1), so when that copy of the last shared_ptr is destroyed, the object is destroyed and the pointer to the object is invalid.
(I am not sure why you are returning a shared_ptr and not a unique_ptr here.)
The proper use of a smart pointer, or any class that "owns" (controls the lifetime of) other resources (resources that you are still allowed to access directly), is to keep the "smart" pointer/owner alive as long as you need to access the ressource.
So the "smart" pointer (owning object) needs to be named. Also, I am not sure that you really would want to hide the fact that it is a smart pointer from the view of the reader with auto.
std::shared_pointer<Bar> foo = getSharedPointer();
// use foo.get()
You may want to hide the exact type of managed object:
std::shared_pointer<auto> foo = getSharedPointer();
This question already has answers here:
Taking the address of a temporary object
(7 answers)
Closed 7 years ago.
I have two code segments which I expected the same outcome:
First one:
SomeClass somefunc(...){
SomeClass newObj;
//some codes modify this object
return newObj;
}
int main(){
SomeClass *p;
p = &(somefuc(...));
}
Second one:
SomeClass *somefunc(...){
SomeClass newObj;
//some codes modify this object
return &newObj;
}
int main(){
SomeClass *p;
p = somefunc(...);
}
Why is it I got a "taking the address of a temporary object" error when I tried to build the first code segment, while the second code segment doesn't produce an error?
Before you even think about this, you need to learn the rules of temporary lifetime.
The broad case is that a temporary object is destroyed at the end of the full-expression creating it. The implication is that if
SomeClass *p;
p = &(somefunc(...));
were allowed to work, p would be a dangling pointer, targeting an object that no longer exists.
The big exception to the above rule is that when a reference with automatic lifetime is directly bound to the temporary object, the lifetime of the temporary is extended to be equal to the lifetime of the reference. Note that this does not cover const T& make_lvalue(const T& t) { return t; } because the reference isn't binding directly, nor class member references.
There are a few cases which are completely safe, in which the address of the temporary is only used immediately and not stored for later. e.g.
memcpy(buffer, &f(), sizeof(decltype(f())));
Of course, this results in the "address of a temporary" error you're encountered, but you can work around it via
memcpy(buffer, std::addressof(f()), sizeof(decltype(f())));
But do NOT store the resulting pointer.
The first snippet does rightfully not compile because, as the compiler said, you cannot take the address of a temporary object because it would be destroyed at the end of the expression (here: the assignment). Thus, saving its address would be meaningless.
The second snippet does compile, but is still incorrect although it might seem to work for the reasons stated here (at least if you try to access the object through the pointer).
The first example does not compile because somefunc returns a value, and you attempt to take the address of this temporary thing it returns. This would work:
Someclass* p;
Someclass val = somefunc (...);
p = &val;
The second example does not compile -- or shouldn't -- because somefunc is supposed to return a Someclass, but instead it returns a pointer to a Someclass. Make it return Someclass* and then it should compile -- but now you're returning a pointer to a local variable, which no longer exists after you leave the function. Best solution is the first example, as patched here.
Suppose I have:
class SomeObject {
};
SomeObject& f() {
SomeObject *s = new SomeObject();
return *s;
}
// Variant 1
int main() {
SomeObject& s = f();
// Do something with s
}
// Variant 2
int main() {
SomeObject s = f();
// Do something with s
}
Is there any difference between the first variant and the second? any cases I would use one over the other?
Edit: One more question, what does s contain in both cases?
First, you never want to return a reference to an object which
was dynamically allocated in the function. This is a memory
leak waiting to happen.
Beyond that, it depends on the semantics of the object, and what
you are doing. Using the reference (variant 1) allows
modification of the object it refers to, so that some other
function will see the modified value. Declaring a value
(variant 2) means that you have your own local copy, and any
modifications, etc. will be to it, and not to the object
referred to in the function return.
Typically, if a function returns a reference to a non-const,
it's because it expects the value to be modified; a typical
example would be something like std::vector<>::operator[],
where an expression like:
v[i] = 42;
is expected to modify the element in the vector. If this is
not the case, then the function should return a value, not
a reference (and you should almost never use such a function to
initialize a local reference). And of course, this only makes
sense if you return a reference to something that is accessible
elsewhere; either a global variable or (far more likely) data
owned by the class of which the function is a member.
In the first variant you attach a reference directly to a dynamically allocated object. This is a rather unorthodox way to own dynamic memory (a pointer would be better suited for that purpose), but still it gives you the opportunity to properly deallocate that object. I.e. at the end of your first main you can do
delete &s;
In the second variant you lose the reference, i.e. you lose the only link to that dynamically allocated object. The object becomes a memory leak.
Again, owning a dynamically allocated object through a reference does not strike me as a good practice. It is usually better to use a pointer or a smart pointer for that purpose. For that reason, both of your variants are flawed, even though the first one is formally redeemable.
Variant 1 will copy the address of the object and will be fast
Variant 2 will copy the whole object and will be slow (as already pointed out in Variant2 you cant delete the object which you created by calling new)
for the edit: Both f contain the same Object
None of the two options you asked about is very good. In this particular case you should use shared_ptr or unique_ptr, or auto_ptr if you use older C++ compilers, and change the function so it returns pointer, not reference. Another good option is returning the object by value, especially if the object is small and cheap to construct.
Modification to return the object by value:
SomeObject f() { return SomeObject(); }
SomeObject s(f());
Simple, clean, safe - no memory leaking here.
Using unique_ptr:
SomeObject* f() { return new SomeObject(); }
unique_ptr<SomeObject> s(f());
One of the advantages of using a unique_ptr or shared_ptr here is that you can change your function f at some point to return objects of a class derived from SomeObject and none of your client code will need to be changed - just make sure the base class (SomeObject) has a virtual constructor.
Why the options you were considering are not very good:
Variant 1:
SomeObject& s = f();
How are you going to destroy the object? You will need address of the object to call it's destructor anyway, so at some point you would need to dereference the object that s refers to (&s)
Variant 2. You have a leak here and not a chance to call destructor of the object returned from your function.
When using shared_ptr, should I just use the shared_ptr declaration once or declare shared_ptr everywhere I pass it?
So in the function where I new up the instance I wrap it in a shared_ptr but when I return it from the function I could also return a shared_ptr or, using the get() on the shared_ptr, just return a normal pointer.
So my question is, should I just use shared_ptr<myType> when I new the instance and then pass normal pointers around or should I be passing shared_ptr<myType> everywhere?
Creating a shared_ptr doesn't imbue magical powers on its pointee object. The magic is all in the shared_ptr — and its copies — itself. If you stop using it, you lose your reference counting; worse, because you used it at some point, the object will be automatically deleted when you don't expect it.
The whole point of having shared_ptr is that you know your object won't get destroyed when you're still using it somewhere.
In the following:
T* foo() {
shared_ptr<T> sp(new T());
return sp.get();
// ^ the only shared_ptr<T> referencing the obj is dead;
// obj is deleted;
// returned pointer invalid before you can even do anything with it
}
your pointer is immediately invalid.
There may well be circumstances in which you extract a raw pointer, but these should be rare. If you are in a function where you know you don't need the reference counting, then just pass the shared_ptr in by reference.
When you want to return an instance from a method, do you create the object and send a pointer back, or a reference back? Whats the correct method and the method signature for this?
There are a lot of ways to do this in C++. Unfortunately most of them result in confusion on who is responsible for allocating and deallocating the object. There are two methods that I recommend:
// Return a real object, automatic stack allocation.
Foo GetFoo1()
{
Foo f;
// Init f.
return f;
}
// Use a smart, reference counted pointer that handles deallocation itself.
boost::shared_ptr<Foo> GetFoo2()
{
boost::shared_ptr<Foo> f(new Foo);
// Init f
return f;
}
The answer depends on what exactly you are doing and who is responsible for deallocating.
First method: allocate on the heap and return. Who ever called the function will be responsible for deleting the returned pointer.
SomeObject* constructObject ()
{
SomeObject* obj = new SomeObject ();
return obj;
}
Then in some other function
void functionThatNeedsObject ()
{
SomeObject* obj = constructObject ();
//You must delete obj when done
}
Second method: Return a reference. You must be careful not to go out of scope by returning local or temporary variables.
Dont do this:
int& DoubleValue(int nX)
{
int nValue = nX * 2;
return nValue; // return a reference to nValue here
} // nValue goes out of scope here
You can return references to member variables or variables passed as arguments to the function.
SomeStruct& RefFunction(SomeStruct& nX, SomeStruct& nY)
{
return nX;
} //nX is still in scope because it was passed to us
Either return by value (people incorrectly assume that this is slow) or, if you're returning an override of a polymorphic type, return an auto_ptr (or better a unique_ptr in C++0x).
The reason you do NOT use a shared_ptr is that you can never get your pointer out of it and use a different ownership semantic.
Never return a reference to a local instance.
If I'm creating an instance purely to return, I would return by value as first preference.
Only if the object type was not practically copyable would I consider returning via a smart pointer encapsulating the transfer of ownership.
Returning a reference I reserve for returning a reference to an object whose ownership isn't being transferred out of the function, that is it is already owned by something else and it's existence is guaranteed until a defined time after the function returns.
If you're referring to something like a Factory Method, typically you return a pointer. Better still, return a smart pointer and you don't create more leaks by virtue of using a raw pointer.
Example:
std::auto_ptr<Gizmo> MyFactory::CreateGizmo()
{
return new Gizmo;
}
This really depends on the scope of your instance which controls the lifetime of the instance. If this is a local instance, you may return by value but will incur the cost of constructing & destructing the object twice (unless you use RVO). The other option is to return a pointer by constructing the object in the heap inside your function. However, with this approach the client will be responsible for deleting the allocated memory & is always prone to memory leaks. This is why you will need to use some kind of a smart pointer. Anders Abel code clearly illustrates the above two approaches with code examples. BTW, you cannot return a reference to a local instance since the instance will go out of scope once the function ends.