Hi if I am creating something on the stack using new I declare it like:
object *myObject = new object(contr, params);
Is there a way to declare this such as:
object *myObject;
myObject = new object(constr, params);
Is this correct?
Yes, that is correct. But new does not create things on the stack, it creates them on the heap.
To create object on the stack you would do:
object myObject(constr, params);
There is no other way to create an object on the stack and once it is created on the stack you can't "recreate" it with the same name later in the same function.
As others have said, new will create *myObject on the heap. For completeness I'll point out that the pointer to the object, called myObject (note there is no *) does reside on the stack the way you declared it. Since stack variables go out of scope when you leave a function, you must delete the object before returning, or transfer the pointer to another variable with a longer lifetime. Neglecting to delete a heap object whose pointer is in a stack variable before returning from a function is sort of the canonical memory leak scenario (though far from the only one)
Yes that is correct but it won't allocate on the stack. Instead it will allocate on the heap. If you want to allocate on the stack, declare it this way
object myObject(contr,params);
If you want the object to be on the stack, you need to say
object myObject(contr, params);
This code:
object *myObject;
myObject = new object(constr, params);
...is legal & correct. But please please initialize myObject to something when you allocate it. Remember 'myObject' is itself not an instance of the 'object', but an instance of a pointer to an 'object'. So when you declare this pointer like this:
object *myObject;
...you are leaving it uninitialized. Instead, do this:
object *myObject = 0;
myObject = new object(constr, params);
...and when you delete it:
delete myObject;
myObject = 0;
People may debate that you should set it to NULL rather than 0, but both are fine as far as the language is concerned and this is mostly a matter of style and what your coworkers are used to.
Related
This is my first question on stack overflow. Apologies if this is a "dumb" question, but I'm currently learning C++, and I'm a little confused by something. As I understand it, in the code below, the variable "myVariable" is declared on the heap but instantiated in the constructor on the stack. So where does it "live" - on the heap or the stack?
class MyClass{
int _myVariable;
MyClass(int i){
_myVariable = i;
}
}
The member variable is allocated according to how class is instantiated.
void example() {
MyClass a{17}; // This allocates memory on stack
MyClass *b = new MyClass(17); // This allocates memory on heap
}
"Stack" and "Heap" are implementation details. The C++ standard defines Automatic Storage and Dynamic Storage.
The most common implementations for the storage of variables are stack and heap, respectively.
The new operator makes an object live on the dynamic storage:
MyClass* mc = new MyClass(14);.
Note how we now need to use a pointer to access it.
With automatic storage, we can omit the pointer semantics:
MyClass mc = MyClass(14); // constructs an object on the automatic storage.
The object lifetime is managed - you've guessed - automatically. More precisely until the end of the scope.
With dynamically allocated objects, you have to manage the lifetime of the objects yourself.
There are cases where you can't use automatic storage: Namely polymorphism.
If MyClass is polymorphic (that means, it has virtual functions), you can't put it into the automatic storage since the compiler needs to know the size of an object. Since with polymorphism, the size of the pointed-to object can change at runtime it's not possible to create it on the automatic storage.
MyClass c = MyClass2(); //Object Slicing
c.foo(); // calls MyClass::foo()
MyClass* cc = new MyClass2(); //No Object Slicing
cc->foo(); // calls MyClass2::foo();
There are helper classes that take away the responsibility to clean up your memory:
unique_ptr and shared_ptr (although the latter is used rarely).
In the given code, nothing is allocated, you have a mere class declaration.
It is contradictory (and wrong) that "myVariable" is declared on the heap while instantiated in the constructor on the stack.
A simple constructor like yours does no allocation, it just assigns value upon creation of a class instance. Constructors do not allocate the instance, destructors do not deallocate it.
The allocation being done on the heap or on the stack will depend on how you use the class (as a plain variable or with a pointer).
It depends on where does the object live. If the actual object is on the heap the variable also lives on the heap. If the object lives on the stack the variable also lives on the stack.
Look at this example:
MyClass myObject = MyClass(5); // myObject lives on the stack and thus the variable i for myObject also lives on the stack
MyClass* newObject = new MyClass(5); // newObject is allocated on the heap and the variable i for newObject lives on the heap
delete newObject; // since newObject is created using new we must free the memory after use
I'm trying to understand the concept behind pointers.
I have a function in which i set an pointer to an object as an attribute of a struct:
void util::setobject(string s)
{
Document* d;
d->Parse(s.c_str());
message.payload = d;
{
Outside this function i can call the message object and access the document. Now I call this function for the second time so I overwrite the payload and set a new pointer to a new document. As far as I know, the old document object still exists but nothing points to it correct? Is this object then removed automatically?
Thanks!
Edit
Sorry I totally messed up this code example.
So I have two options here:
Option 1: Stay with pointers
void util::setobject(string s)
{
Document* d = new Document();
d->Parse(s.c_str());
message.payload = d;
{
To avoid a memory leak i would need to delete the pointed object before assigning new value, correct?
void util::setobject(string s)
{
Document* d = new Document();
d->Parse(s.c_str());
delete message.payload; // correct?
message.payload = d;
{
Second option: Avoid using "new"
void util::setobject(string s)
{
Document d;
d.Parse(s.c_str());
message.payload = d; // object is copied to struct attribute
{
S.th. like that wouldn't work because d goes out of scope:
void util::setobject(string s)
{
Document d;
d.Parse(s.c_str());
message.payload = &d; // does not make sense correct?
{
This might be s.th. off-topic, but the second version would require the struct to look like that:
struct MESSSAGE
{
string topic;
bool done = true;
Document payload;
}
Document comes from <rapidjson/document.h>. Doing it without a pointer results in multiple errors:
error: use of deleted function 'Message::Message(const Message&)'
'rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>::GenericDocument(const rapidjson::GenericDocument<Encoding, Allocator, StackAllocator>&) [with Encoding=rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; StackAllocator=rapidjson::CrtAllocator]' is private within this context
Does anyone also know how to interpret these errors? I think that the copy constructor of Document is private, therefore I need to use pointer here, correct?
Who deletes pointer (not created with new) in C++?
As long as the program is well defined, no one deletes pointer-not-created-with-new because only pointer-created-with-allocating-new may be deleted.
Document* d;
d->Parse(s.c_str());
The behaviour of this example is undefined because you indirect through an uninitialised pointer and attempt to call a member function through it.
message.payload = d;
Here, you copy an indeterminate value. Behaviour is undefined because of this as well.
... an can be used like this
You are mistaken. No pointer can be used like this.
so I overwrite the payload and set a new pointer to a new document.
In the example, you don't set pointer to a "new document". You never created a document in the example.
As far as I know, the old document object still exists
If message.payload used to point to a document object, then that object still exists. You haven't demonstrated such case in the example.
but nothing points to it correct?
Depends. There can be many pointers to an object, so overwriting one pointer doesn't necessarily mean that there are no pointers to the object any more. But indeed, this is a possible case - that wasn't demonstrated in the example.
Is this object then removed automatically?
Depends on the storage class of the object. automatic objects are destroyed automatically (hint is in the name) when they go out of scope. Static objects are destroyed automatically when the program ends. Thread local objects are destroyed automatically when the thread exits. Temporary objects are destroyed automatically at the end of full expression (sometimes extended).
Dynamic objects are not destroyed automatically. They are destroyed only when explicitly destroyed or deleted. If last pointer to dynamic object is overwritten, that object is said to have been leaked. Well, dynamic trivial objects can be destroyed automatically by creating another object in its place, but dynamic memory is not deallocated automatically.
Regarding the edited question;
To avoid a memory leak i would need to delete the pointed object before assigning new value, correct?
Depends on what the old pointer points to. If it points to a dynamic object created with allocating new and there are no other pointers responsible for the deletion, then yes. Otherwise, no.
Does anyone also know how to interpret these errors?
Document is not (publicly) copyable, and you attempted to copy Message which contains such non-copyable document.
There is no Document in your code, hence there is nothing you could delete.
What this function does
void util::setobject(string s)
{
Document* d;
d->Parse(s.c_str());
message.payload = d;
}
is the following:
It declares d as a pointer to a Document and leaves that pointer uninitialized. The second line then dereferences that uninitialized pointer and causes undefined behavior.
I suggest you to read Why should C++ programmers minimize use of 'new'?, because your function should actually look like this:
void util::setobject(string s)
{
Document d;
d.Parse(s.c_str());
message.payload = d;
}
If you cannot / do not want to change payload to be a Document (not a pointer), then you need to create a Document:
Document* d = new Document;
However, you should not use raw pointers here. Look at std::shared_ptr or std::unique_ptr. Raw pointers should not be owning memory. To "own" something means to be responsible to delete it. Smart pointers do that for you, while raw owning pointers are a recipe for desaster and should be avoided (don't misunderstand: raw pointers are fine, the problem is owning raw pointers).
To answer the title question: No-one.
Only pointers that point to objects allocated by new should be deleted and only pointers that point to objects allocated by new[] should be delete[]d.
Pointers to objects that have static1, thread local2 or automatic3 storage duration must not be deleted, the language specifies how and when those objects are destroyed.
"Global" objects
"Per-thread global" objects
"On-the-Stack" objects
So I have a class called List which stores a vector of pointers to classes of type Object. List has a function called add which initialises an Object class and adds it's pointer to the vector. I thought that once the add function ended that the Object class would be destroyed and accessing the pointer would cause an exception. When I wrote a test program to test this it turned out that the Object class was never destroyed.
Are classes initialised inside a function ever destroyed once the function ends?
When are classes automatically destroyed?
Depends how you're creating the object. If you are doing it like this:
void add() {
Object obj;
vec.push_back(&obj);
}
Then you are creating obj with automatic storage duration. That means it will be destroyed when the add function ends. The pointer you have pushed into the vector will no longer point to a valid Object, so definitely don't do this.
You may, however, be doing this:
void add() {
Object* obj = new Object();
vec.push_back(obj);
}
If you are, you are creating the Object with dynamic storage duration and it will not be destroyed at the end of the function. The pointer you push into the vector will remain valid. However, if you do this, you need to remember to delete the object at a later time. If you don't, you'll have a leak.
The best option is to avoid using pointers at all, if you can. Just make the vector a std::vector<Object> and copy objects into it:
void add() {
vec.push_back(Object());
}
Or in C++11:
void add() {
vec.emplace_back();
}
If you really need pointers, prefer smart pointers.
In C++, if you don't use any memory manager, smart pointers or some kind of "managed" environment, classes created using keyword new. To avoid misunderstanding could you please post constructor of Object and method List.Add?
So, when you are creating new object like:
Object* o = new Object();
you reserving space in the heap and store pointer to that space in pointer 'o'. If you never calling
delete o;
explicitly your object will never deleted.
Example:
Class *_obj1;
Class *_obj2;
void doThis(Class *obj) {}
void create() {
Class *obj1 = new Class();
Class obj2;
doThis(obj1);
doThis(&obj2);
_obj1 = obj1;
_obj2 = &obj2;
}
int main (int argc, const char * argv[]) {
create();
_obj1->doSomething();
_obj2->doSomething();
return 0;
}
This creates 2 objects, creates pointers to them, then main() calls a method on each. The Class object creates a char* and stores the C string "Hello!" in it; the ~Class() deallocator frees the memory. The doSomething() method prints out "buff: %s" using printf(). Simple enough. Now if we run it we get this:
Dealloc
Buff: Hello!
Buff: ¯ø_ˇ
Obviously the stack object does not work here - it's obvious that when the function exits the pointer _obj2 is pointing at a location in the stack. This is why I used heap objects in my previous question, which people told me was "stupid".
So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer, not an arrogant "you're doing it wrong" as so many have done. Because in this case stack objects cannot work so heap objects seem to be the only way. EDIT: Also, converting back to a stack object would be useful as well.
The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap. So what's the right way to do it?
So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer,
The straight answer is: You can't "convert" an object between the stack and heap. You can create a copy of the object that lives in the other space, as others have pointed out, but that's it.
The second question: the specific example of heap objects being "wrong" was creating a new vector* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.
Dynamically allocating STL objects will not on its own corrupt the heap. (No idea where you might have heard that.)
If you want to use a stack-allocated STL object outside of the function that you created it in, you can't, since the stack space in which the object resides is only valid inside the function that created it.
You can, however, return a copy of the object:
std::vector<char> SomeFunc()
{
std::vector<char> myvector;
// myvector.operations ...
return myvector;
}
As I said, though, this will return a copy of the object, not the original object itself -- that would be impossible, since the stack that contains the object is unwound after the function returns.
One other option is to have the caller pass in a reference / pointer to the object that your function manipulates, if this makes sense for your particular scenario:
void SomeFunc(std::vector<char>& destination)
{
// destination.operations ...
}
void AnotherFunc()
{
std::vector<char> myvector;
SomeFunc(myvector);
}
As you can see, you've still allocated everything on the stack, and you avoid the (sometimes consequential) overhead of relying on the copy-constructor to return a copy of the object.
So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits?
This line:
_obj2 = &obj2;
Change to:
_obj2 = new Class(obj2); // Create an object on the heap invoking the copy constructor.
I want a straight answer, not an arrogant "you're doing it wrong" as so many have done.
Thats as straight an answer as you can get. Obviously you are new to C++, So I am sure this will nto work as intended because you have probably made a couple of mistakes in the defintion of the class "Class" (by the way terrible name).
Also, converting back to a stack object would be useful as well.
class obj3(*_obj2); // dereference the heap object pass it to the copy constructor.
The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way?
Why do you dynamically allocate the vector. Just create it locally.
std::vector<std::string> funct()
{
std::vector<std::string> vecString;
// fill your vector here.
return vecString; // Notice no dynamic allocation with new,
}
Using new/delete is using C++ like C. What you need to read up on is smart pointers. These are obejcts that control the lifespan of the object and automatically delete the object when they go out of scope.
std::auto_ptr<Class> x(new Class);
Here x is a smart pointer (of type auto_ptr) when it goes out of scope the object will be deleted. But you can return an auto_ptr to the calling function and it will be safely transfered out of the function. Its actually a lot more complicated than that and you need a book.
Obviously if you create them as stack objects it fails because they're immediately deallocated,
Its de'allocated when it goes out of scope.
but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.
If you do it incorrectly. Which given your knowledge is very likely. But hard to verify since you have not provided the definition of Class.
So what's the right way to do it?
Learn why you should use stack objects
Learn what smart pointers are.
Learn how to use smart pointers to control lifespans of objects.
Learn the different types of smart pointers.
Look up what the separation of concerns is (you are not following this basic principle).
You have to either copy-construct a new heap object (Class * foo = new Class(obj2)) or assign the stack object to a heap object (*obj1 = obj2).
the only way is to copy object.
Change declaration to:
Class _obj2;
and assign:
_obj2 = obj2;
Taking the address of a stack variable won't magically transfer it into heap. You need to write a proper copy-constructor for your class and use _obj2 = new Class(obj2);.
As for STL containers, they allocate their data on the heap anyway, why would you want to allocate container itself on the heap? Put them in a scope that will keep them alive as long as you need them.
Your stack object is created inside the create function and is deallocated as soon you get out of scope of the function. The pointer is invalid.
You could change Class* obj2 to Class obj2 and the assign (which means copy) the object by obj2 = obj2;
I think you're really trying to ask "How can I return an object created inside my function?" There are several valid ways:
Allocate on the heap and return a pointer
Use an automatic variable and return its value, not a pointer (the compiler will copy it)
Let the caller provide storage, either by pointer or reference parameter, and build your object there.
I declared a private variable
vector<SomeClass> theVector;
someplace inside my SomeClass class.
Why can't I say: delete theVector inside my SomeClass destructor?
The compiler error says:
type `class Vector<SomeClass>' argument given to `delete', expected pointer
What expected pointer?
If new and delete go hand in hand.
To delete something you need to create it via new (which gives you a pointer). You can then delete the pointer. The way you are declaring the vector it is being created on the stack (not the heap) and will be deallocated when it goes out of scope.
int main()
{
vector<SomeClass> theVector;
vector<SomeClass>* ptrVctor = new vector<SomeClass>();
delete ptrVctor; // ptrVctor must be deleted manually
// theVector destroyed automatically here
}
In C++ (unlike Java), you can create objects either on the stack or the heap. An example of creating it on the stack is, as you have done:
vector<SomeClass> theVector;
This object goes out of scope when the stack frame disappears (normally when you return from the function that created the object.
Creating objects on the heap allows them to outlive the function that created them and you do that by performing:
vector<SomeClass> *theVectorPtr = new vector<SomeClass>();
You can then pass the theVectorPtr pointer back to the caller of the function (or store it globally, whatever you want).
In order to get rid of the object on the heap, you explicitly delete it:
delete theVectorPtr;
somewhere in your code.
Deleting an object on the heap ends the scope of that object, the same way returning from a function ends the scope of variables created on the stack.
If an object (rather than a value) is defined as a class member variable, then its storage is always tied to the object instance of that class.
Therefore, if the containing object is allocated on the stack, then that object and the field will die when the stack unrolls.
If the containing object is allocated on the heap, then the field object will die when the entire containing object dies with delete.
You will only be applying delete to a field if that is a pointer, since all that is stored with the containing object is the address of some other memory area, and you are deleting the materials in that area.
The memory for theVector is part of the memory allocated for the SomeClass object, so you can't delete it without deleting the entire SomeClass object. The memory for theVector will get automatically freed when the SomeClass object is destructed.
This is because theVector is not a pointer, which is what delete' expects. "Expected pointer" means the operand ofdelete' must be a pointer.
Compare this to
int theInt;
delete theInt;
It surely will generate an error similar to what you got.
To destroy all of the objects held in the vector, you would do the following:
theVector.resize(0);
This will happen automatically when the vector goes out of scope.
c++ gives you flexibility to create object in stack and heap.
When the object is created in heap through new operator as shown below it returns the pointer to the object in heap.
ClassA * pobj_class = new ClassA();
For object created in stack the constructor returns the object rather than pointer as shown below.
ClassA obj_class();
and stack object automatically destroyed when variable(obj_class) goes out of scope,but object created on heap lives for ever.So to destroy heap object c++ gives you delete operator that takes pointer as argument and destroys the object the pointer is pointing to.