For example this class:
class RTPIPv4Address{
public:
RTPIPv4Address(int a, int b);
}
Silly question but... I just stumbled on code which initialized a class instance like that with for example
RTPIPv4Address adr(2,2);
Now I am wondering, is this just another syntax for the usual
RTPIPv4Address* adr = new RTPIPv4Address (2,2);
or does it have any other effects? For example, given the lack of a pointer and a new(), is it declared on the stack like other local variables do and then get deallocated at function return or is it saved on the heap and therefore persist?
Thanks in advance
Yes, the first example is stack-allocated and will have it's destructor called and be deallocated as soon as the variable loses scope. For a local variable, this usually happens when the function returns, though you can force it to lose scope earlier with curly braces.
function
{
RTPIPv4Address adr(2,2);
return; //adr loses scope and destructor is called
}
That's how it's normally allocated on the stack and where it loses scope, but it can happen other places as well.
function
{
if (condition)
{
RTPIPv4Address adr(2, 2);
//do stuff with adr
} //adr loses scope and destructor is called
//do more stuff
return;
}
The two both construct an object but apart from that are very dissimilar. The first constructs on the stack, the second on the heap. The first form should be used wherever possible. The second form should be used if and only if you need the object to persist, or, it is too large to fit on the stack. new is not the "usual" form of object creation at all in C++.
The first example will stack-allocate your object. The only way to get something on the heap is via new (and, obviously, malloc or other low-level operations like mmap).
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.
In one function. I create a local arrray. char arr[20];
And before end of this function.
Will compiler do garbage collection for me? Or I need to do delete by myself?
There is no Garbage Collection in C++.
However, if you use automatic variables, they will be destroyed when they fall out of scope.
As a rule, there should be 1 delete call for every new. If you have no new, you don't delete.
You don't have to delete this array since you create it on stack.
If you created the array using new then you would have to use delete to clean up.
Local variables are destroyed at the end of the block (not necessarily function) in which they're created. For example:
void myfunc() {
int x[some_size];
if (something) {
std::vector<std::string> y;
// ...
} // y will be destroyed here
// more code
} // x will be destroyed here
If you want your array destroyed earlier than the exit from the function, you may want to make use of the same:
void f() {
// come code here
{
int x[size];
// code that uses x
} // `x` gets destroyed here
// more code
}
I should add, however, that destroying the variable at that point may not affect memory usage. The memory isn't needed after you exit from the inner block, but it may not be released immediately either.
On the other hand, if you use something like std::vector instead of explicit dynamic allocation, destroying the object will (immediately) free the memory that was being used to store the object's data.
Any local variables (including arrays) are created on the stack, and therefore are reclaimed when the function returns.
You can think of this similar to garbage collection, but the details are very different. If you do more of any kind of programming, you should learn more about other languages (it is similar in most languages).
So no, you do not need to do anything with your local array.
Variables only exist within the function they're defined in. Once that function terminates, they're gone. You only need to delete/free your variables if you manually allocated the memory with a new or malloc type command.
I am still new to C++. I have found that you can instantiate an instance in C++ with two different ways:
// First way
Foo foo;
foo.do_something();
// Second way
Baz *baz = new Baz();
baz->do_something();
And with both I don't see big difference and can access the attributes. Which is the preferred way in C++? Or if the question is not relevant, when do we use which and what is the difference between the two?
Thank you for your help.
The question is not relevant: there's no preferred way, those just do different things.
C++ both has value and reference semantics. When a function asks for a value, it means you'll pass it a copy of your whole object. When it asks for a reference (or a pointer), you'll only pass it the memory address of that object. Both semantics are convertible, that is, if you get a value, you can get a reference or a pointer to it and then use it, and when you get a reference you can get its value and use it. Take this example:
void foo(int bar) { bar = 4; }
void foo(int* bar) { *bar = 4; }
void test()
{
int someNumber = 3;
foo(someNumber); // calls foo(int)
std::cout << someNumber << std::endl;
// printed 3: someNumber was not modified because of value semantics,
// as we passed a copy of someNumber to foo, changes were not repercuted
// to our local version
foo(&someNumber); // calls foo(int*)
std::cout << someNumber << std::endl;
// printed 4: someNumber was modified, because passing a pointer lets people
// change the pointed value
}
It is a very, very common thing to create a reference to a value (i.e. get the pointer of a value), because references are very useful, especially for complex types, where passing a reference notably avoids a possibly costly copy operation.
Now, the instantiation way you'll use depends on what you want to achieve. The first way you've shown uses automatic storage; the second uses the heap.
The main difference is that objects on automatic storage are destroyed with the scope in which they existed (a scope being roughly defined as a pair of matching curly braces). This means that you must not ever return a reference to an object allocated on automatic storage from a regular function, because by the time your function returns, the object will have been destroyed and its memory space may be reused for anything at any later point by your program. (There are also performance benefits for objects allocated on automatic storage because your OS doesn't have to look up a place where it might put your new object.)
Objects on the heap, on the other hand, continue to exist until they are explicitly deleted by a delete statement. There is an OS- and platform-dependant performance overhead to this, since your OS needs to look up your program's memory to find a large enough unoccupied place to create your object at. Since C++ is not garbage-collected, you must instruct your program when it is the time to delete an object on the heap. Failure to do so leads to leaks: objects on the heap that are no longer referenced by any variable, but were not explicitly deleted and therefore will exist until your program exits.
So it's a matter of tradeoff. Either you accept that your values can't outlive your functions, or you accept that you must explicitly delete it yourself at some point. Other than that, both ways of allocating objects are valid and work as expected.
For further reference, automatic storage means that the object is allocated wherever its parent scope was. For instance, if you have a class Foo that contains a std::string, the std::string will exist wherever you allocate your Foo object.
class Foo
{
public:
// in this context, automatic storage refers to wherever Foo will be allocated
std::string a;
};
int foo()
{
// in this context, automatic storage refers to your program's stack
Foo bar; // 'bar' is on the stack, so 'a' is on the stack
Foo* baz = new Foo; // 'baz' is on the heap, so 'a' is on the heap too
// but still, in both cases 'a' will be deleted once the holding object
// is destroyed
}
As stated above, you cannot directly leak objects that reside on automatic storage, but you cannot use them once the scope in which they were created is destroyed. For instance:
int* foo()
{
int a; // cannot be leaked: automatically managed by the function scope
return &a; // BAD: a doesn't exist anymore
}
int* foo()
{
int* a = new int; // can be leaked
return a; // NOT AS BAD: now the pointer points to somewhere valid,
// but you eventually need to call `delete a` to release the memory
}
The first way -- "allocating on the stack" -- is generally faster and preferred much of the time. The constructed object is destroyed when the function returns. This is both a blessing -- no memory leaks! -- and a curse, because you can't create an object that lives for a longer time.
The second way -- "allocating on the heap" is slower, and you have to manually delete the objects at some point. But it has the advantage that the objects can live on until you delete them.
The first way allocates the object on the stack (though the class itself may have heap-allocated members). The second way allocates the object on the heap, and must be explicitly delete'd later.
It's not like in languages like Java or C# where objects are always heap-allocated.
They do very different things. The first one allocates an object on the stack, the 2nd on the heap. The stack allocation only lasts for the lifetime of the declaring method; the heap allocation lasts until you delete the object.
The second way is the only way to dynamically allocate objects, but comes with the added complexity that you must remember to return that memory to the operating system (via delete/delete[]) when you are done with it.
The first way will create the object on the stack, and the object will go away when you return from the function it was created in.
The second way will create the object on the heap, and the object will stick around until you call delete foo;.
If the object is just a temporary variable, the first way is better. If it's more permanent data, the second way is better - just remember to call delete when you're finally done with it so you don't build up cruft on your heap.
Hope this helps!
Using C++:
I currently have a method in which if an event occurs an object is created, and a pointer to that object is stored in a vector of pointers to objects of that class. However, since objects are destroyed once the local scope ends, does this mean that the pointer I stored to the object in the vector is now null or undefined? If so, are there any general ways to get around this - I'm assuming the best way would be to allocate on the heap.
I ask this because when I try to access the vector and do operations on the contents I am getting odd behavior, and I'm not sure if this could be the cause or if it's something totally unrelated.
It depends on how you allocate the object. If you allocate the object as an auto variable, (i.e. on the stack), then any pointer to that object will become invalid once the object goes out of scope, and so dereferencing the pointer will lead to undefined behavior.
For example:
Object* pointer;
{
Object myobject;
pointer = &myobject;
}
pointer->doSomething(); // <--- INVALID! myobject is now out of scope
If, however, you allocate the object on the Heap, using the new operator, then the object will remain valid even after you exit the local scope. However, remember that there is no automatic garbage collection in C++, and so you must remember to delete the object or you will have a memory leak.
So if I understand correctly you have described the following scenario:
class MyClass
{
public:
int a;
SomeOtherClass b;
};
void Test()
{
std::vector<MyClass*> v;
for (int i=0; i < 10; ++i)
{
MyClass b;
v.push_back(&b);
}
// now v holds 10 items pointers to strange and scary places.
}
This is definitely bad.
There are two primary alternatives:
allocate the objects on the heap using new.
make the vector hold instances of MyClass (i.e. std::vector<MyClass>)
I generally prefer the second option when possible. This is because I don't have to worry about manually deallocating memory, the vector does it for me. It is also often more efficient. The only problem, is that I would have to be sure to create a copy constructor for MyClass. That means a constructor of the form MyClass(const MyClass& other) { ... }.
If you store a pointer to an object, and that object is destroyed (e.g. goes out of scope), that pointer will not be null, but if you try to use it you will get undefined behavior. So if one of the pointers in your vector points to a stack-allocated object, and that object goes out of scope, that pointer will become impossible to use safely. In particular, there's no way to tell whether a pointer points to a valid object or not; you just have to write your program in such a way that pointers never ever ever point to destroyed objects.
To get around this, you can use new to allocate space for your object on the heap. Then it won't be destroyed until you delete it. However, this takes a little care to get right as you have to make sure that your object isn't destroyed too early (leaving another 'dangling pointer' problem like the one you have now) or too late (creating a memory leak).
To get around that, the common approach in C++ is to use what's called (with varying degrees of accuracy) a smart pointer. If you're new to C++ you probably shouldn't worry about these yet, but if you're feeling ambitious (or frustrated with memory corruption bugs), check out shared_ptr from the Boost library.
If you have a local variable, such as an int counter, then it will be out of scope when you exit the function, but, unless you have a C++ with a garbage collector, then your pointer will be in scope, as you have some global vector that points to your object, as long as you did a new for the pointer.
I haven't seen a situation where I have done new and my memory was freed without me doing anything.
To check (in no particular order):
Did you hit an exception during construction of member objects whose pointers you store?
Do you have a null-pointer in the container that you dereference?
Are you using the vector object after it goes out of scope? (Looks unlikely, but I still have to ask.)
Are you cleaning up properly?
Here's a sample to help you along:
void SomeClass::Erase(std::vector<YourType*> &a)
{
for( size_t i = 0; i < a.size(); i++ ) delete a[i];
a.clear();
}
In my browsings amongst the Internet, I came across this post, which includes this
"(Well written) C++ goes to great
lengths to make stack automatic
objects work "just like" primitives,
as reflected in Stroustrup's advice to
"do as the ints do". This requires a
much greater adherence to the
principles of Object Oriented
development: your class isn't right
until it "works like" an int,
following the "Rule of Three" that
guarantees it can (just like an int)
be created, copied, and correctly
destroyed as a stack automatic."
I've done a little C, and C++ code, but just in passing, never anything serious, but I'm just curious, what it means exactly?
Can someone give an example?
Stack objects are handled automatically by the compiler.
When the scope is left, it is deleted.
{
obj a;
} // a is destroyed here
When you do the same with a 'newed' object you get a memory leak :
{
obj* b = new obj;
}
b is not destroyed, so we lost the ability to reclaim the memory b owns. And maybe worse, the object cannot clean itself up.
In C the following is common :
{
FILE* pF = fopen( ... );
// ... do sth with pF
fclose( pF );
}
In C++ we write this :
{
std::fstream f( ... );
// do sth with f
} // here f gets auto magically destroyed and the destructor frees the file
When we forget to call fclose in the C sample the file is not closed and may not be used by other programs. (e.g. it cannot be deleted).
Another example, demonstrating the object string, which can be constructed, assigned to and which is destroyed on exiting the scope.
{
string v( "bob" );
string k;
v = k
// v now contains "bob"
} // v + k are destroyed here, and any memory used by v + k is freed
In addition to the other answers:
The C++ language actually has the auto keyword to explicitly declare the storage class of an object. Of course, it's completely needless because this is the implied storage class for local variables and cannot be used anywhere. The opposite of auto is static (both locally and globall).
The following two declarations are equivalent:
int main() {
int a;
auto int b;
}
Because the keyword is utterly useless, it will actually be recycled in the next C++ standard (“C++0x”) and gets a new meaning, namely, it lets the compiler infer the variable type from its initialization (like var in C#):
auto a = std::max(1.0, 4.0); // `a` now has type double.
Variables in C++ can either be declared on the stack or the heap. When you declare a variable in C++, it automatically goes onto the stack, unless you explicitly use the new operator (it goes onto the heap).
MyObject x = MyObject(params); // onto the stack
MyObject * y = new MyObject(params); // onto the heap
This makes a big difference in the way the memory is managed. When a variable is declared on the stack, it will be deallocated when it goes out of scope. A variable on the heap will not be destroyed until delete is explicitly called on the object.
Stack automatic are variables which are allocated on the stack of the current method. The idea behind designing a class which can acts as Stack automatic is that it should be possible to fully initialize it with one call and destroy it with another. It is essential that the destructor frees all resources allocated by the object and its constructor returns an object which has been fully initialized and ready for use. Similarly for the copy operation - the class should be able to be easily made copies, which are fully functional and independent.
The usage of such class should be similar to how primitive int, float, etc. are used. You define them (eventually give them some initial value) and then pass them around and in the end leave the compiler to the cleaning.
Correct me if i'm wrong, but i think that copy operation is not mandatory to take full advantage of automatic stack cleaning.
For example consider a classic MutexGuard object, it doesn't need a copy operation to be useful as stack automatic, or does it ?