How does the object unique_ptr<A> behaves if it's passed anonymously (or to no variable at all). How is it possible to know whether the unique_ptr has reference (it's being set into named variable) from within the c'tor.
basically the example shows calling method get() method directly from returned value object.
class A
{
public:
A(int a):_a(a) {}
~A() { std::cout << "d'tor A " << _a << std::endl; }
int _a;
};
std::unique_ptr<A> f1()
{
auto p1 = std::make_unique<A>(1);
return p1;
}
A *f2()
{
A * x = std::make_unique<A>(2).get(); // d'tor called 2
std::cout << x->_a << std::endl; // this will print 2 although destructed.
return x;
}
A *f3()
{
return std::make_unique<A>(3).get(); // d'tor called 3
}
int main(int argc, const char * argv[]) {
auto a=f1();
auto b=f2();
auto c=f3();
return 0;
} // d'tor called 1
In the above code, I understand the timing of the d'tor A 1 call, since when exiting the block where the unique referrer (denoted by local variable a) is destroyed.
But I don't understand the other 2 flows (d'tor A 2 and d'tor A 3 that called on the line of the creation - see in example). does it means that reference count in those cases is 0 from the first place, or that it raises to 1 and reduced right after.
P.S
This case intrigued me although it doesn't relate to any real case, but to clarify a concept that I tackled by accident.
It happens because I converted java-script where it's costumed to create a member and use it without intermediate variable (for example a().b().c() instead of _a=a(); _b=_a.b(); _c=_b.c()) and I accidentally used this notation on my c++ code.
You're confusing the lifetime of the std::unique_ptr and the object that it manages, with the lifetime of the pointer that you can get using it's get method.
A std::unique_ptr is the only owner of a dynamically allocated object, when it's destructor is called, it will call a deleter helper function on the pointer it is holding (in case of std::make_unique, it will just call delete or delete[], whichever is appropriate in this case)
In 1st case, the type of variable a, is std::unique_ptr<A>, the std::unique_ptr lives on the stack, (you didn't have to call std::move thanks to copy-elision), and when the main function finishes, it's removed from the stack, destructor is called, and the object is deleted, which is the behavior we usually want when using std::unique_ptr.
Now, 2nd and 3rd case, are the same, the 2nd case just introduces a temporary variable, but it doesn't change anything.
A * x = std::make_unique<A>(2).get();
When called like that, you create a temporary std::unique_ptr<A>, and on that temporary, you call get method, that returns a copy of the pointer that's managed. The issue is that the temporary std::unique_ptr<A> is destroyed at the end of the line, and the pointer you have is dangling, it has been already deleted. Dereferencing it and using in anyway is undefined behavior, and anything can happen.
3rd case is the same, temporary std::unique_ptr, you're getting it's pointer, but the temporary is removed, so delete is called on the object it was managing, and we have a danging pointer.
Whenever you have a smart pointer, never call get on a temporary, 1st store the temporary in a local variable, so it doesn't go out of scope when you're still using the pointer it is managing.
Related
I have a simple C++ code, but I don't know how to use the destructor:
class date {
public:
int day;
date(int m)
{
day =m;
}
~date(){
cout << "I wish you have entered the year \n" << day;
}
};
int main()
{
date ob2(12);
ob2.~date();
cout << ob2.day;
return 0;
}
The question that I have is, what should I write in my destructor code, that after calling the destructor, it will delete the day variable?
Rarely do you ever need to call the destructor explicitly. Instead, the destructor is called when an object is destroyed.
For an object like ob2 that is a local variable, it is destroyed when it goes out of scope:
int main()
{
date ob2(12);
} // ob2.~date() is called here, automatically!
If you dynamically allocate an object using new, its destructor is called when the object is destroyed using delete. If you have a static object, its destructor is called when the program terminates (if the program terminates normally).
Unless you create something dynamically using new, you don't need to do anything explicit to clean it up (so, for example, when ob2 is destroyed, all of its member variables, including day, are destroyed). If you create something dynamically, you need to ensure it gets destroyed when you are done with it; the best practice is to use what is called a "smart pointer" to ensure this cleanup is handled automatically.
You do not need to call the destructor explicitly. This is done automatically at the end of the scope of the object ob2, i.e. at the end of the main function.
Furthermore, since the object has automatic storage, its storage doesn’t have to be deleted. This, too, is done automatically at the end of the function.
Calling destructors manually is almost never needed (only in low-level library code) and deleting memory manually is only needed (and only a valid operation) when the memory was previously acquired using new (when you’re working with pointers).
Since manual memory management is prone to leaks, modern C++ code tries not to use new and delete explicitly at all. When it’s really necessary to use new, then a so-called “smart pointer” is used instead of a regular pointer.
You should not call your destructor explicitly.
When you create your object on the stack (like you did) all you need is:
int main()
{
date ob2(12);
// ob2.day holds 12
return 0; // ob2's destructor will get called here, after which it's memory is freed
}
When you create your object on the heap, you kinda need to delete your class before its destructor is called and memory is freed:
int main()
{
date* ob2 = new date(12);
// ob2->day holds 12
delete ob2; // ob2's destructor will get called here, after which it's memory is freed
return 0; // ob2 is invalid at this point.
}
(Failing to call delete on this last example will result in memory loss.)
Both ways have their advantages and disadvantages. The stack way is VERY fast with allocating the memory the object will occupy and you do not need to explicitly delete it, but the stack has limited space and you cannot move those objects around easily, fast and cleanly.
The heap is the preferred way of doing it, but when it comes to performance it is slow to allocate and you have to deal with pointers. But you have much more flexibility with what you do with your object, it's way faster to work with pointers further and you have more control over the object's lifetime.
Only in very specific circumstances you need to call the destructor directly. By default the destructor will be called by the system when you create a variable of automatic storage and it falls out of scope or when a an object dynamically allocated with new is destroyed with delete.
struct test {
test( int value ) : value( value ) {}
~test() { std::cout << "~test: " << value << std::endl; }
int value;
};
int main()
{
test t(1);
test *d = new t(2);
delete d; // prints: ~test: 2
} // prints: ~test: 1 (t falls out of scope)
For completeness, (this should not be used in general) the syntax to call the destructor is similar to a method. After the destructor is run, the memory is no longer an object of that type (should be handled as raw memory):
int main()
{
test t( 1 );
t.~test(); // prints: ~test: 1
// after this instruction 't' is no longer a 'test' object
new (&t) test(2); // recreate a new test object in place
} // test falls out of scope, prints: ~test: 2
Note: after calling the destructor on t, that memory location is no longer a test, that is the reason for recreation of the object by means of the placement new.
In this case your destructor does not need to delete the day variable.
You only need to call delete on memory that you have allocated with new.
Here's how your code would look if you were using new and delete to trigger invoking the destructor
class date {
public: int* day;
date(int m) {
day = new int;
*day = m;
}
~date(){
delete day;
cout << "now the destructor get's called explicitly";
}
};
int main() {
date *ob2 = new date(12);
delete ob2;
return 0;
}
Even though the destructor seems like something you need to call to get rid of or "destroy" your object when you are done using it, you aren't supposed to use it that way.
The destructor is something that is automatically called when your object goes out of scope, that is, when the computer leaves the "curly braces" that you instantiated your object in. In this case, when you leave main(). You don't want to call it yourself.
You may be confused by undefined behavior here. The C++ standard has no rules as to what happens if you use an object after its destructor has been run, as that's undefined behavior, and therefore the implementation can do anything it likes. Typically, compiler designers don't do anything special for undefined behavior, and so what happens is an artifact of what other design decisions were made. (This can cause really weird results sometimes.)
Therefore, once you've run the destructor, the compiler has no further obligation regarding that object. If you don't refer to it again, it doesn't matter. If you do refer to it, that's undefined behavior, and from the Standard's point of view the behavior doesn't matter, and since the Standard says nothing most compiler designers will not worry about what the program does.
In this case, the easiest thing to do is to leave the object untouched, since it isn't holding on to resources, and its storage was allocated as part of starting up the function and will not be reclaimed until the function exits. Therefore, the value of the data member will remain the same. The natural thing for the compiler to do when it reads ob2.day is to access the memory location.
Like any other example of undefined behavior, the results could change under any change in circumstances, but in this case they probably won't. It would be nice if compilers would catch more cases of undefined behavior and issue diagnostics, but it isn't possible for compilers to detect all undefined behavior (some occurs at runtime) and often they don't check for behavior they don't think likely.
So I have an abstract class, called MyClassParent, which MyClass inherits from. I run the following code:
for(auto e:elements){
MyClass m = *this;
MyClass * mpointer = &m;
if(mpointer->xLargerthanY(x,y)){
rv.push_back(unique_ptr<MyClassParent>(mpointer));
if(!rv[0]->solved()) cout<<"true";//works as expected
}
}
rv[0]->solved();//gives pure virtual function called error
What's strange is that rv[0]->solved() inside the for each loop works as expected, returns true if the object has x greater than y. But if I call the function from outside the for each loop, I get a pure virtual function called error, which should never happen since I override solved() in the child class. I suspect this has something to do with the unique_ptr function, as my solved method makes no changes to the object and only return true of false.
I have tested this with many other methods, they all work inside the for each loop, but as soon as I exit it, I get the pure virtual function called error.
rv[0]->solved();//gives pure virtual function called error
Of course it does. Your program has undefined behavior, so it can do anything. It's also fairly easy to distill that snippet into what's causing the problem:
MyClass *ptr;
{
MyClass m;
ptr = &m;
}
ptr->solved();
Once we get rid of all of those red herrings, we see that all the pointers in your rv container point to objects with automatic storage durations, that have since gone out of scope. Using them to access that object is just going to behave in some undefined manner.
If you want to have rv store owning pointers to copies of this, then create those copies with dynamic storage duration
for(auto e:elements){
MyClass& m = *this; // Assuming we need the reference binding
if(m.xLargerthanY(x,y)){
rv.push_back(make_unique<MyClass>(m));
}
}
And now everything points at valid objects.
Ok, let's start with a little introduction because you seem to not have a grasp on some things needed to understand smart pointers:
Automatic storage duration: the lifetime of an object is managed by the compiler. Its lifetime is defined by the scope of the variable associated.
E.g.:
{
X x; // lifetime of x starts here
// ....
} // lifetime of x ends here
Dynamic storage duration: the lifetime of an object is managed by the programmer. It starts with a call to new and ends with a call to delete (this is simplified a bit).
E.g.:
auto foo(X* x)
{
delete x; // lifetime ends with delete
}
{
X* x = new X{}; // lifetime starts with new
foo(x);
}
In C++ you should never explicitly call new / delete and use smart pointers instead.
unique_ptr (unless specified otherwise) on destruction will automatically call delete on the pointer it helds. This is the reason it must be provided with a pointer to a dynamic object i.e. allocated with new. This is one of your problems.
X x;
std::unique_ptr<X> p{&x};
// p receives a pointer to an automatic storage duration
// this is 100% wrong. The destructor for x would be called twice
// once as part of the automatic lifetime of x
// and then as part of the destructor of p
// resulting in UB
this is what you do here:
MyClass m = ...;
MyClass * mpointer = &m;
unique_ptr<MyClassParent>(mpointer);
// unique_ptr receives a pointer to an automatic storage duration object
As if that weren't enough the other problem you have is that you access a dangling pointer.
The scope of m is within the for. The vector holds pointers to such objects and those objects go out of scope after each iteration. When you do rv[0] you access an object whose lifetime has ended. Undefined behavior again.
I hope you have a better understanding of what unique_ptr does and what problem it solves. The solution is - as Storry Teller showed - to use make_unique.
What make_unique does: it calls new and creates an unique_ptr from that pointer returned by new. You could do this by hand yourself but you shouldn't because of other problems: Differences between std::make_unique and std::unique_ptr
As pointed by #StoryTeller this is undefined behavior, but let me explain why it behaves the way it does in this case. Since it is undefined behavior, there is no guarantee it will behave this way in different compilers or systems, but I will explain why there is a good chance it will:
for(auto e:elements){
MyClass m = *this;
MyClass * mpointer = &m;
if(mpointer->xLargerthanY(x,y)){
rv.push_back(unique_ptr<MyClassParent>(mpointer));
if(!rv[0]->solved()) cout<<"true";//works as expected
}
}
rv[0]->solved();//gives pure virtual function called error
Here
for(auto e:elements){
MyClass m = *this;
....
}
A pointer to m is stored into the rv vector. But when m exists scope, the object is being destroyed. The code implicitly calls MyClass::~MyClass(), which in the end replaces the virtual table of the object. First the derived class is being destroyed, and at the last step of this destruction the virtual table is replaced so that the object no has the virtual table of the base. In the base, solved() is pure virtual, so calling:
rv[0]->solved();
so calling this function finds the definition of the base, only. The derived object no longer exists, so it can't be used. In this case, in the base class, resolved() is pure virtual, and has no body. That's why it crashes the way it does. If you had a non-virtual resolved() in the base, then there is a good chance that you'd have a different crash, since the object had been destroyed already.
Note that even if this code did not crash, then later on, when rv is destroyed things become messy. The pointers inside rv point to the stack, but std::unique_ptr calls delete and assumes that the object is on the heap. Either that will crash immediately, since this is an illegal pointer, the heap/stack will be trashed, or it will be simply ignored. The exact behavior is unknown, since this is also undefined behavior.
Here is a simpler case when you'd get a similar problem:
class Base
{
public:
virtual ~Base() { bar(); }
virtual void foo() = 0;
void bar() { foo(); }
};
class Derived: public Base
{
public:
void foo() override { };
};
int main()
{
Derived b;
}
I have the following codes to dynamically allocate a class object in a function call:
#include <iostream>
class A
{
public:
A(){std::cout<<"Constructing..."<<std::endl;}
~A(){std::cout<<"Deconstructing..."<<std::endl;}
};
A & f()
{
std::cout<<"Calling f()"<<std::endl;
A * pa = new A();
std::cout<<"End calling f()"<<std::endl;
return *pa;
}
int main()
{
A & b = f();
}
The output are:
Calling f()
Constructing...
End calling f()
which means that the class object was never deleted.
However, if I change the line in main to:
A b = f();
the outputs are:
Calling f()
Constructing...
End calling f()
Deconstructing...
which means the class object was deleted automatically.
Why that assigning a reference to a non-reference will change its dynamic behavior?
There's no change to the dynamic object created by new. That's not destroyed in either case, since it can only be destroyed by explicit use of delete.
In the second case, you create a second object b by copying the dynamic object. Being automatic, that is destroyed when it goes out of scope, so you see a Deconstructing... message from that.
Since it was initialised by a copy constructor, not the default constructor, you don't see a corresponding Constructing... message. You could add a copy constructor to see that:
A(A const &){std::cout<<"Copying..."<<std::endl;}
giving the output
Calling f()
Constructing...
End calling f()
Copying...
Deconstructing...
In general, always use smart pointers and other RAII types to manage dynamic resources, to avoid memory leaks and other lifetime confusion issues.
In the case of
A & b = f();
b refers to the object created on the heap.
In the case of
A b = f();
b creates a copy (possible move) of the data on the heap. This one is destructed when the function exits (when b goes out of scope).
The object on the heap is left alone, in both cases.
To explore this further, the addition of the copy constructor would help A(A const&) and then printed a message, or even making it private and noting the compilation errors aid in marking the copies and their locations.
Note: when you new an object in a function and then don't destroy it, or don't move the pointer to some other owner, you will leak memory. Favour library utilities like unique_ptr or share_ptr to manage the resource (RAII).
When you declare a value type, it is constructed on the stack and the compiler takes care of calling its destructor when it goes out of scope. However, when you create the instance on the heap by calling new, the compiler can't know when the instance is not needed any more and therefor it's up to the programmer to indirectly call its destructor by using delete. The fact that you have a reference to the object on the heap doesn't provide the compiler with any knowledge of when the object has to be destroyed.
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.
I have a simple C++ code, but I don't know how to use the destructor:
class date {
public:
int day;
date(int m)
{
day =m;
}
~date(){
cout << "I wish you have entered the year \n" << day;
}
};
int main()
{
date ob2(12);
ob2.~date();
cout << ob2.day;
return 0;
}
The question that I have is, what should I write in my destructor code, that after calling the destructor, it will delete the day variable?
Rarely do you ever need to call the destructor explicitly. Instead, the destructor is called when an object is destroyed.
For an object like ob2 that is a local variable, it is destroyed when it goes out of scope:
int main()
{
date ob2(12);
} // ob2.~date() is called here, automatically!
If you dynamically allocate an object using new, its destructor is called when the object is destroyed using delete. If you have a static object, its destructor is called when the program terminates (if the program terminates normally).
Unless you create something dynamically using new, you don't need to do anything explicit to clean it up (so, for example, when ob2 is destroyed, all of its member variables, including day, are destroyed). If you create something dynamically, you need to ensure it gets destroyed when you are done with it; the best practice is to use what is called a "smart pointer" to ensure this cleanup is handled automatically.
You do not need to call the destructor explicitly. This is done automatically at the end of the scope of the object ob2, i.e. at the end of the main function.
Furthermore, since the object has automatic storage, its storage doesn’t have to be deleted. This, too, is done automatically at the end of the function.
Calling destructors manually is almost never needed (only in low-level library code) and deleting memory manually is only needed (and only a valid operation) when the memory was previously acquired using new (when you’re working with pointers).
Since manual memory management is prone to leaks, modern C++ code tries not to use new and delete explicitly at all. When it’s really necessary to use new, then a so-called “smart pointer” is used instead of a regular pointer.
You should not call your destructor explicitly.
When you create your object on the stack (like you did) all you need is:
int main()
{
date ob2(12);
// ob2.day holds 12
return 0; // ob2's destructor will get called here, after which it's memory is freed
}
When you create your object on the heap, you kinda need to delete your class before its destructor is called and memory is freed:
int main()
{
date* ob2 = new date(12);
// ob2->day holds 12
delete ob2; // ob2's destructor will get called here, after which it's memory is freed
return 0; // ob2 is invalid at this point.
}
(Failing to call delete on this last example will result in memory loss.)
Both ways have their advantages and disadvantages. The stack way is VERY fast with allocating the memory the object will occupy and you do not need to explicitly delete it, but the stack has limited space and you cannot move those objects around easily, fast and cleanly.
The heap is the preferred way of doing it, but when it comes to performance it is slow to allocate and you have to deal with pointers. But you have much more flexibility with what you do with your object, it's way faster to work with pointers further and you have more control over the object's lifetime.
Only in very specific circumstances you need to call the destructor directly. By default the destructor will be called by the system when you create a variable of automatic storage and it falls out of scope or when a an object dynamically allocated with new is destroyed with delete.
struct test {
test( int value ) : value( value ) {}
~test() { std::cout << "~test: " << value << std::endl; }
int value;
};
int main()
{
test t(1);
test *d = new t(2);
delete d; // prints: ~test: 2
} // prints: ~test: 1 (t falls out of scope)
For completeness, (this should not be used in general) the syntax to call the destructor is similar to a method. After the destructor is run, the memory is no longer an object of that type (should be handled as raw memory):
int main()
{
test t( 1 );
t.~test(); // prints: ~test: 1
// after this instruction 't' is no longer a 'test' object
new (&t) test(2); // recreate a new test object in place
} // test falls out of scope, prints: ~test: 2
Note: after calling the destructor on t, that memory location is no longer a test, that is the reason for recreation of the object by means of the placement new.
In this case your destructor does not need to delete the day variable.
You only need to call delete on memory that you have allocated with new.
Here's how your code would look if you were using new and delete to trigger invoking the destructor
class date {
public: int* day;
date(int m) {
day = new int;
*day = m;
}
~date(){
delete day;
cout << "now the destructor get's called explicitly";
}
};
int main() {
date *ob2 = new date(12);
delete ob2;
return 0;
}
Even though the destructor seems like something you need to call to get rid of or "destroy" your object when you are done using it, you aren't supposed to use it that way.
The destructor is something that is automatically called when your object goes out of scope, that is, when the computer leaves the "curly braces" that you instantiated your object in. In this case, when you leave main(). You don't want to call it yourself.
You may be confused by undefined behavior here. The C++ standard has no rules as to what happens if you use an object after its destructor has been run, as that's undefined behavior, and therefore the implementation can do anything it likes. Typically, compiler designers don't do anything special for undefined behavior, and so what happens is an artifact of what other design decisions were made. (This can cause really weird results sometimes.)
Therefore, once you've run the destructor, the compiler has no further obligation regarding that object. If you don't refer to it again, it doesn't matter. If you do refer to it, that's undefined behavior, and from the Standard's point of view the behavior doesn't matter, and since the Standard says nothing most compiler designers will not worry about what the program does.
In this case, the easiest thing to do is to leave the object untouched, since it isn't holding on to resources, and its storage was allocated as part of starting up the function and will not be reclaimed until the function exits. Therefore, the value of the data member will remain the same. The natural thing for the compiler to do when it reads ob2.day is to access the memory location.
Like any other example of undefined behavior, the results could change under any change in circumstances, but in this case they probably won't. It would be nice if compilers would catch more cases of undefined behavior and issue diagnostics, but it isn't possible for compilers to detect all undefined behavior (some occurs at runtime) and often they don't check for behavior they don't think likely.