I'm relatively new to C++ and am having a hard trouble understanding the instantiation of object and pointers to objects.
Whats the difference between these two declaration in terms of memory and usage? :
MyClass obj1;
MyClass *obj2;
And also the specific problem I am having is that I have a class which has an unsigned short array where the last space of the array changes if I do this:
MyClass obj;
obj = MyClass("123");
MyClass has two constructors one which will take an int and as default will assign it to zero and splice it in parts of 3 digits or less. And another which will take a string representation of a number and do the same... hope that makes sense!
It works well if I declare it
MyClass obj = MyClass("123123123");
but not if I do it the other way. Why?
The difference:
MyClass obj1;
MyClass *obj2;
Here obj1 is an instance of MyClass.
While obj2 can potentially hold the address of an instance of MyClass.
Also obj1 will automatically be initialized by the constructors, while obj2 is not initialized by default (and thus points to random memory). Once initialized obj2 may take the special value NULL which indicates that it is not pointing at an object.
obj2 = &obj1;
Here we initialize obj2 to point at the address in memory of obj1. If you change any of the members of obj1 then you can see the changes by looking at them through obj2 (but because obj2 is a pointer you need to de-reference).
obj1.plop = 5;
std::cout << obj1.plop << "\n";
std::cout << obj2->plop << "\n"; Should print the same values.
The following is actually two different things:
MyClass obj;
obj = MyClass("123");
Line one initializes 'obj' with the default constructor.
Line two: creates a temporary object constructed with the string "123". Once this temporary object is created it is copied onto 'obj' using the assignment operator. If you did not define an assignment operator the compiler will have generated one for you. If your class contains pointers then the default version will probably not work correctly (in most other situations the default assignment operator should work fine).
This line probably works:
MyClass obj = MyClass("123123123");
Because the compiler has optimised this into:
MyClass obj("123123123");
When you say MyClass obj1; you create the object. MyClass * obj2; just saves space for the address of the object.
So MyClass obj1; does the following:
it sets up the name in the compiler symbol table
it allocates sizeof(MyClass) bytes of space — could be as big as you want
it runs the default ctor of MyClass, MyClass::MyClass() 9or a ctor that has all default arguments intead) putting the initialized object in the space it allocated
it remembers where that object is, associating it with the name 'obj1' in the symbol table.
while MyClass * obj2; instead
sets up the name obj2 in the symbol table
allocates space only for the address of a MyClass object, sizeof(MyClass*) — probably 4 or 8 bytes
doesn't run any constructor.
When you say MyClass obj; obj = MyClass("123123123") you
create and allocate a MyClass object for obj using the default ctor
create and allocate another MyClass object
assign that new MyClass object to replace the old one.
When you call
MyClass obj = MyClass("123123123");
You are actually creating two objects! The correct way is to call
MyClass obj("123123123");
In the first code, one actually creates the object of type MyClass so it consumes as much space as needed. the other one just defines a pointer, so you reserve as much space as you would need for an addresss on your system (typically 4 bytes, sometimes 8)
When you split your initialization into two lines, you are first creating MyClass with a default constructor, then creating a MyClass with a parameterized constructor, and then using the assignment operator to override the contents of the first with the contents of the second. This is wasteful. Because constructors can have side effects, the compiler would probably not optimize this for you.
In the third piece of code you provided, you are actually using a single constructor that takes a parameter. Not assignment takes place.
The difference between
MyClass obj1;
MyClass *obj2;
Is the first creates an object (size = size of the object), whereas the second only creates a pointer to an object (4 bytes on 32 bit systems) but not the actual object. In order to do that you'd need to do
MyClass* obj2 = new MyClass("123");
This would allocate 4 bytes for the pointer and the x bytes where x is the size of the object. If you manually "new" something like this, then you are responsible for manually destroying it later using "delete".
The MyClass obj1 will be "destroyed" when it goes out of scope.
Two things are affected by these declarations: the lifetime of the variable, and where the memory is allocated.
The pointer version MyClass* is declaring a variable that points at an instance of MyClass. It does not itself allocate it; the allocation from the 'free store' (which is always the same as the 'heap') occurs when you explicitly 'new' it, and is freed when you 'delete' it.
The following code works:
MyClass* test_works() {
MyClass* obj = new MyClass;
return obj;
}
The non-pointer version is allocating the memory in the context it is specified - the declaration might be at a global level, or on the stack in a function, or as a member of another object ('composition') - and it is automatically allocated and freed as it comes in and out of scope.
The following code, for example, will fail:
MyClass* test_crashes() {
MyClass obj;
return &obj;
}
Related
I learned C# first, and now I'm starting with C++. As I understand, operator new in C++ is not similar to the one in C#.
Can you explain the reason of the memory leak in this sample code?
class A { ... };
struct B { ... };
A *object1 = new A();
B object2 = *(new B());
What is happening
When you write T t; you're creating an object of type T with automatic storage duration. It will get cleaned up automatically when it goes out of scope.
When you write new T() you're creating an object of type T with dynamic storage duration. It won't get cleaned up automatically.
You need to pass a pointer to it to delete in order to clean it up:
However, your second example is worse: you're dereferencing the pointer, and making a copy of the object. This way you lose the pointer to the object created with new, so you can never delete it even if you wanted!
What you should do
You should prefer automatic storage duration. Need a new object, just write:
A a; // a new object of type A
B b; // a new object of type B
If you do need dynamic storage duration, store the pointer to the allocated object in an automatic storage duration object that deletes it automatically.
template <typename T>
class automatic_pointer {
public:
automatic_pointer(T* pointer) : pointer(pointer) {}
// destructor: gets called upon cleanup
// in this case, we want to use delete
~automatic_pointer() { delete pointer; }
// emulate pointers!
// with this we can write *p
T& operator*() const { return *pointer; }
// and with this we can write p->f()
T* operator->() const { return pointer; }
private:
T* pointer;
// for this example, I'll just forbid copies
// a smarter class could deal with this some other way
automatic_pointer(automatic_pointer const&);
automatic_pointer& operator=(automatic_pointer const&);
};
automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically
This is a common idiom that goes by the not-very-descriptive name RAII (Resource Acquisition Is Initialization). When you acquire a resource that needs cleanup, you stick it in an object of automatic storage duration so you don't need to worry about cleaning it up. This applies to any resource, be it memory, open files, network connections, or whatever you fancy.
This automatic_pointer thing already exists in various forms, I've just provided it to give an example. A very similar class exists in the standard library called std::unique_ptr.
There's also an old one (pre-C++11) named auto_ptr but it's now deprecated because it has a strange copying behaviour.
And then there are some even smarter examples, like std::shared_ptr, that allows multiple pointers to the same object and only cleans it up when the last pointer is destroyed.
A step by step explanation:
// creates a new object on the heap:
new B()
// dereferences the object
*(new B())
// calls the copy constructor of B on the object
B object2 = *(new B());
So by the end of this, you have an object on the heap with no pointer to it, so it's impossible to delete.
The other sample:
A *object1 = new A();
is a memory leak only if you forget to delete the allocated memory:
delete object1;
In C++ there are objects with automatic storage, those created on the stack, which are automatically disposed of, and objects with dynamic storage, on the heap, which you allocate with new and are required to free yourself with delete. (this is all roughly put)
Think that you should have a delete for every object allocated with new.
EDIT
Come to think of it, object2 doesn't have to be a memory leak.
The following code is just to make a point, it's a bad idea, don't ever like code like this:
class B
{
public:
B() {}; //default constructor
B(const B& other) //copy constructor, this will be called
//on the line B object2 = *(new B())
{
delete &other;
}
}
In this case, since other is passed by reference, it will be the exact object pointed to by new B(). Therefore, getting its address by &other and deleting the pointer would free the memory.
But I can't stress this enough, don't do this. It's just here to make a point.
Given two "objects":
obj a;
obj b;
They won't occupy the same location in memory. In other words, &a != &b
Assigning the value of one to the other won't change their location, but it will change their contents:
obj a;
obj b = a;
//a == b, but &a != &b
Intuitively, pointer "objects" work the same way:
obj *a;
obj *b = a;
//a == b, but &a != &b
Now, let's look at your example:
A *object1 = new A();
This is assigning the value of new A() to object1. The value is a pointer, meaning object1 == new A(), but &object1 != &(new A()). (Note that this example is not valid code, it is only for explanation)
Because the value of the pointer is preserved, we can free the memory it points to: delete object1; Due to our rule, this behaves the same as delete (new A()); which has no leak.
For you second example, you are copying the pointed-to object. The value is the contents of that object, not the actual pointer. As in every other case, &object2 != &*(new A()).
B object2 = *(new B());
We have lost the pointer to the allocated memory, and thus we cannot free it. delete &object2; may seem like it would work, but because &object2 != &*(new A()), it is not equivalent to delete (new A()) and so invalid.
In C# and Java, you use new to create an instance of any class and then you do not need to worry about destroying it later.
C++ also has a keyword "new" which creates an object but unlike in Java or C#, it is not the only way to create an object.
C++ has two mechanisms to create an object:
automatic
dynamic
With automatic creation you create the object in a scoped environment:
- in a function or
- as a member of a class (or struct).
In a function you would create it this way:
int func()
{
A a;
B b( 1, 2 );
}
Within a class you would normally create it this way:
class A
{
B b;
public:
A();
};
A::A() :
b( 1, 2 )
{
}
In the first case, the objects are destroyed automatically when the scope block is exited. This could be a function or a scope-block within a function.
In the latter case the object b is destroyed together with the instance of A in which it is a member.
Objects are allocated with new when you need to control the lifetime of the object and then it requires delete to destroy it. With the technique known as RAII, you take care of the deletion of the object at the point you create it by putting it within an automatic object, and wait for that automatic object's destructor to take effect.
One such object is a shared_ptr which will invoke a "deleter" logic but only when all the instances of the shared_ptr that are sharing the object are destroyed.
In general, whilst your code may have many calls to new, you should have limited calls to delete and should always make sure these are called from destructors or "deleter" objects that are put into smart-pointers.
Your destructors should also never throw exceptions.
If you do this, you will have few memory leaks.
B object2 = *(new B());
This line is the cause of the leak. Let's pick this apart a bit..
object2 is a variable of type B, stored at say address 1 (Yes, I'm picking arbitrary numbers here). On the right side, you've asked for a new B, or a pointer to an object of type B. The program gladly gives this to you and assigns your new B to address 2 and also creates a pointer in address 3. Now, the only way to access the data in address 2 is via the pointer in address 3. Next, you dereferenced the pointer using * to get the data that the pointer is pointing to (the data in address 2). This effectively creates a copy of that data and assigns it to object2, assigned in address 1. Remember, it's a COPY, not the original.
Now, here's the problem:
You never actually stored that pointer anywhere you can use it! Once this assignment is finished, the pointer (memory in address3, which you used to access address2) is out of scope and beyond your reach! You can no longer call delete on it and therefore cannot clean up the memory in address2. What you are left with is a copy of the data from address2 in address1. Two of the same things sitting in memory. One you can access, the other you can't (because you lost the path to it). That's why this is a memory leak.
I would suggest coming from your C# background that you read up a lot on how pointers in C++ work. They are an advanced topic and can take some time to grasp, but their use will be invaluable to you.
Well, you create a memory leak if you don't at some point free the memory you've allocated using the new operator by passing a pointer to that memory to the delete operator.
In your two cases above:
A *object1 = new A();
Here you aren't using delete to free the memory, so if and when your object1 pointer goes out of scope, you'll have a memory leak, because you'll have lost the pointer and so can't use the delete operator on it.
And here
B object2 = *(new B());
you are discarding the pointer returned by new B(), and so can never pass that pointer to delete for the memory to be freed. Hence another memory leak.
If it makes it easier, think of computer memory as being like a hotel and programs are customers who hire rooms when they need them.
The way this hotel works is that you book a room and tell the porter when you are leaving.
If you program books a room and leaves without telling the porter the porter will think that the room is still is use and will not let anyone else use it. In this case there is a room leak.
If your program allocates memory and does not delete it (it merely stops using it) then the computer thinks that the memory is still in use and will not allow anyone else to use it. This is a memory leak.
This is not an exact analogy but it might help.
When creating object2 you're creating a copy of the object you created with new, but you're also losing the (never assigned) pointer (so there's no way to delete it later on). To avoid this, you'd have to make object2 a reference.
It's this line that is immediately leaking:
B object2 = *(new B());
Here you are creating a new B object on the heap, then creating a copy on the stack. The one that has been allocated on the heap can no longer be accessed and hence the leak.
This line is not immediately leaky:
A *object1 = new A();
There would be a leak if you never deleted object1 though.
My question is influenced by Prof. Thomas Cormen's second comment on his Quora answer$.
He says that the constructor carries out the following three tasks:
Allocates memory for the object.
Initializes the instance variables of the object, e.g., by implicitly calling init in Python. (I also emphasize that the init method should initialize not some, but all of the instance variables.)
Returns a reference to (i.e., address of) the object.
However, the MSDN documentation for C++* says that it is the new operator that does that:
Allocates memory for an object or array of objects of type-name from the free store and returns a suitably typed, nonzero pointer to the object.
My question is, who is right? Or, is there something more to it, perhaps like the new operator always calls the constructor, as suggested by a comment on the post?
Thanks.
$ Unfortunately, Quora does not have the option to copy the link for a comment - I can only do so for the answer.
* Although I say C++, I think it is also true for other languages like Java and C# (I am not 100% sure though).
If you search for constructor on the linked MSDN page, it says this:
When new is used to allocate memory for a C++ class object, the object's constructor is called after the memory is allocated.
In other words, a constructor is called if one exists. If none exists, none is called.
When in doubt, read the specification. From en.cppreference.com
The new expression attempts to allocate storage and then attempts to
construct and initialize either a single unnamed object, or an unnamed
array of objects in the allocated storage. The new-expression returns
a prvalue pointer to the constructed object or, if an array of objects
was constructed, a pointer to the initial element of the array.
Constructor does not allocate memory.
new allocates memory, then calls the proper constructor.
Semi pseudo code here :
template <typename T>
T* new(Args... arguments_to_constructor_of_T_if_any)
{
void* mem = malloc(sizeof(T)); // Allocate memory
// Call constructor
// Compiler will produce machine code to construct object T over memory mem.
(mem) T(arguments_to_constructor_of_T_if_any);
return (T*)(mem);
}
An example :
class A
{
int a;
int b;
A(int a, int b) { this->a = a; this->b = b; };
}
int main()
{
A* a = new A(3, 4);
// After compiled, code above will look like :
void* mem = malloc(sizeof(A));
// Below is A(int, int) constructor
((T*) mem)-> a = 3;
((T*) mem)-> b = 4;
}
While I understand that this is probably not the best of ideas, I ask hypothetically:
Is it legal to (i.e. defined behavior) to invoke an object's
destructor manually, and then reuse the memory for another object?
Definitions:
class A {
int a, b, c;
A() {}
~A() {}
}
A createObject() {
A object;
return object;
}
Code:
A* object = new A();
// Use object...
object->~A();
*object = createObject();
You can't call the assignment operator on a destroyed object like you are doing. At least not generally, though it might work with some types. What you can do is this though:
A* object = new A();
object->~A();
// Placement new.
// Constructs a new object in the memory pointed to by object pointer.
// Doesn't allocate memory.
new (object) A(createObject());
You can even use placement new to construct objects of a different type in that memory, as long as they fit. Just be sure of two things:
Don't ever construct an object on top of an already existing object that has not been destructed.
Don't ever call delete on a pointer after you've called the destructor on the object it points to until you've re-construced an object (of the same type) in its place.
Calling a destructor explicitly is a legal thing to do - in fact, that's what you do when you use placement new. Initializing an object "in place", when the memory is already allocated, is also a legal thing do do, but you should do it differently: rather than using the assignment operator, you could use this syntax:
object = new (object) A(); // Placement syntax
The way you did it (with an assignment operator) is incorrect, because you are calling a function (i.e. the assignment operator) on an object the destructor of which has completed.
First i am from JAVA.
In java we create class object like this.
Example example=new Example();
The Example class can have constructor or cannot have constructor.
I can use the same in c++ like this
Example* example=new Example();
Where constructor is compulsory.
From this tutorial http://www.cplusplus.com/doc/tutorial/classes/
I got that we can create object like this.
Example example;
Which do not require an constructor.
I have two questions.
What is the difference between both the way of creating class objects.
If I am creating object like Example example; how to use that in an singleton class.
like I usually do like this.
Sample* Singleton::get_sample() {
if (sample == NULL) {
sample = new Sample();
}
return sample;
}
Please guide me if I am wrong.
I can use the same in c++ like this [...] Where constructor is compulsory. From this tutorial I got that we can create object like this [...] Which do not require an constructor.
This is wrong. A constructor must exist in order to create an object. The constructor could be defined implicitly by the compiler under some conditions if you do not provide any, but eventually the constructor must be there if you want an object to be instantiated. In fact, the lifetime of an object is defined to begin when the constructor routine returns.
From Paragraph 3.8/1 of the C++11 Standard:
[...] The lifetime of an object of type T begins when:
— storage with the proper alignment and size for type T is obtained, and
— if the object has non-trivial initialization, its initialization is complete.
Therefore, a constructor must be present.
1) What is the difference between both the way of creating class objects.
When you instantiate object with automatic storage duration, like this (where X is some class):
X x;
You are creating an object which will be automatically destroyed when it goes out of scope. On the other hand, when you do:
X* x = new X();
You are creating an object dynamically and you are binding its address to a pointer. This way, the object you created will not be destroyed when your x pointer goes out of scope.
In Modern C++, this is regarded as a dubious programming practice: although pointers are important because they allow realizing reference semantics, raw pointers are bad because they could result in memory leaks (objects outliving all of their pointers and never getting destroyed) or in dangling pointers (pointers outliving the object they point to, potentially causing Undefined Behavior when dereferenced).
In fact, when creating an object with new, you always have to remember destroying it with delete:
delete x;
If you need reference semantics and are forced to use pointers, in C++11 you should consider using smart pointers instead:
std::shared_ptr<X> x = std::make_shared<X>();
Smart pointers take care of memory management issues, which is what gives you headache with raw pointers. Smart pointers are, in fact, almost the same as Java or C# object references. The "almost" is necessary because the programmer must take care of not introducing cyclic dependencies through owning smart pointers.
2) If i am creating object like Example example; how to use that in an singleton class.
You could do something like this (simplified code):
struct Example
{
static Example& instance()
{
static Example example;
return example;
}
private:
Example() { }
Example(Example const&) = delete;
Example(Example&&) = delete;
Example& operator = (Example const&) = delete;
Example& operator = (Example&&) = delete;
};
Example example;
This is a declaration of a variable named example of type Example. This will default-initialize the object which involves calling its default constructor. The object will have automatic storage duration which means that it will be destroyed when it goes out of scope.
Example* example;
This is a declaration of a variable named example which is a pointer to an Example. In this case, default-initialization leaves it uninitialized - the pointer is pointing nowhere in particular. There is no Example object here. The pointer object has automatic storage duration.
Example* example = new Example();
This is a declaration of a variable named example which is a pointer to an Example. This pointer object, as above, has automatic storage duration. It is then initialized with the result of new Example();. This new expression creates an Example object with dynamic storage duration and then returns a pointer to it. So the example pointer is now pointing to that dynamically allocated object. The Example object is value-initialized which will call a user-provided constructor if there is one or otherwise initialise all members to 0.
Example* example = new Example;
This is similar to the previous line. The difference is that the Example object is default-initialized, which will call the default constructor of Example (or leave it uninitialized if it is not of class type).
A dynamically allocated object must be deleted (probably with delete example;).
There is two ways to make/create object in c++.
First one is :
MyClass myclass; // if you don;t need to call rather than default constructor
MyClass myclass(12); // if you need to call constructor with parameters
Second one is :
MyClass *myclass = new MyClass();// if you don;t need to call rather than default constructor
MyClass *myclass = new MyClass(12);// if you need to call constructor with parameters
In c++ if you use new keyword, object will be stored in heap. it;s very useful if you are using this object long time of period and if you use first method, it will be stored in stack. it can be used only short time period. Notice : if you use new keyword, remember it will return pointer value. you should declare name with *. If you use second method, it doesn;t delete object in the heap. you must delete by yourself using delete keyword;
delete myclass;
1) What is the difference between both the way of creating class objects.
a) pointer
Example* example=new Example();
// you get a pointer, and when you finish it use, you have to delete it:
delete example;
b) Simple declaration
Example example;
you get a variable, not a pointer, and it will be destroyed out of scope it was declared.
2) Singleton C++
This SO question may helps you
First of all, both cases calls a constructor. If you write
Example *example = new Example();
then you are creating an object, call the constructor and retrieve a pointer to it.
If you write
Example example;
The only difference is that you are getting the object and not a pointer to it. The constructor called in this case is the same as above, the default (no argument) constructor.
As for the singleton question, you must simple invoke your static method by writing:
Example *e = Singleton::getExample();
1)What is the difference between both the way of creating class
objects.
First one is a pointer to a constructed object in heap (by new).
Second one is an object that implicitly constructed. (Default constructor)
2)If i am creating object like Example example; how to use that in an
singleton class.
It depends on your goals, easiest is put it as a member in class simply.
A sample of a singleton class which has an object from Example class:
class Sample
{
Example example;
public:
static inline Sample *getInstance()
{
if (!uniqeInstance)
{
uniqeInstance = new Sample;
}
return uniqeInstance;
}
private:
Sample();
virtual ~Sample();
Sample(const Sample&);
Sample &operator=(const Sample &);
static Sample *uniqeInstance;
};
Example example;
Here example is an object on the stack.
Example* example=new Example();
This could be broken into:
Example* example;
....
example=new Example();
Here the first statement creates a variable example which is a "pointer to Example". When the constructor is called, memory is allocated for it on the heap (dynamic allocation). It is the programmer's responsibility to free this memory when it is no longer needed. (C++ does not have garbage collection like java).
In the first case you are creating the object on the heap using new.
In the second case you are creating the object on the stack, so it will be disposed of when going out of scope.
In C++ you'll need to delete objects on the heapexplicitly using delete when you don't Need them anymore.
To call a static method from a class, do
Singleton* singleton = Singleton::get_sample();
in your main-function or wherever.
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 9 years ago.
While designing a class that dynamically allocates memory I ran into the following problem regarding memory allocation. I was hoping that some of you might be able to point me in the right direction as to how I should design my class in a better way. My class dynamically allocates memory and therefore also deletes it in its destructor.
In order to illustrate the problem, consider the following silly class declaration:
class testClass{
int* data;
public:
testClass(){
data = new int;
*data = 5;
}
~testClass(){
delete data;
}
};
So far so good. Now suppose that I create one of these objects in main
int main(){
testClass myObject;
return 0;
}
Still no issues of course. However, suppose that I now write a function that takes a testClass object as an input and call this from main.
void doNoting(testClass copyOfMyObject){
//do nothing
}
int main(){
testClass myObject;
doNothing(myObject);
return 0;
}
This time around, the function creates a local variable, copyOfMyObject, that's simply a copy of myObject. Then when the end of that function is reached, that local object automatically has its destructor called which deletes the memory pointed to by its data pointer. However, since this is the same memory pointed to by myObject's data pointer, myObject inadvertently has its memory deleted in the process. My question is: what is a better way to design my class?
When you call doNothing(), it is making a copy of your testClass object, because it is being passed by value. Unfortunately, when this copy is destroyed, it calls the destructor, which deletes the same data used by the original instance of testClass.
You want to learn about "copy constructors", and "passing by reference". That is, you should define a copy constructor for your class so that when a copy is made of an instance, it allocates its own memory for its data member. Also, rather than passing by value, you could pass a pointer or a reference to doNothing(), so that no copy is made.
You should create a copy constructor, that is a constructor of the form:
testClass::testClass(const testClass &o)
{
// appropriate initialization here
}
In your case, "appropriate initialization" might mean allocate a new chunk of memory and copy the memory from the old chunk into the new chunk. Or it may mean doing reference counting. Or whatever.
You should also read more about the Rule of Three right here on StackOverflow!
Here's a guideline from an authority: A class with any of {destructor, assignment operator, copy constructor} generally needs all 3
You need a copy constructor that will make a new allocated int for your data, that will then destruct that, but not affect the original.
Alternately, you can make a private copy constructor that's blank, which effectively disables it, forcing your users to pass by reference, or another non-copying way of doing things.