I was wondering how to write the operator = so that the existing allocated memory on a variable be deallocated.
For instance, in the code below, when reassigning the x pointer x = new ClassExample(4), the old x->a memory would be deallocated.
Apparently, when using new, the operator = doesn't apply (it's only for already existing values).
Is there any method of doing this (free old memory when alloc new memory)?
#include <iostream>
#include <cstdlib>
class ClassExample {
public:
int* a;
ClassExample& operator= (const ClassExample& rightSide) {
//.....
}
ClassExample(int val) {
a = new int(val);
}
};
int main()
{
ClassExample* x = new ClassExample(2);
x = new ClassExample(4);
return 0;
}
Never break this rule: every new has to be balanced with a delete.
You could use a smart pointer to achieve what you want, or, in your specific case something simpler:
Briefly, you build a WrappedPtr<T> template class for data type T, which holds a T* pointer. As a starting point, you can define an assignment operator which will delete a currently wrapped object before taking the new one as its member data. You will need to take care with copy construction; or even forbid it.
A true smart pointer will also implement reference counting in some way.
See http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm
The operator= means you are changing the value inside your current object.
Here, you are just changing the pointer x.
The way you could do it is :
ClassExample x(2);
x = ClassExample(4);
Or, in your case, something like:
ClassExample* x = new ClassExample(2);
*x = *(new ClassExample(4));
This last one will introduce leak in your program, so do NOT use it.
Of course, you can use something in between, like:
ClassExample* x = new ClassExample(2);
*x = ClassExample(4);
This one won't leak.
Related
board *gameBoard = new board(givenX,givenY,givenMineCount);
I know that the above statement declares an object pointer that points to board.
But I'm wondering what the statement below means.
board gameBoard = *new board(givenX,givenY,givenMineCount);
In both statements the "new" keyword returns a pointer to the object you are allocating. The reason the second statement works is because if you put a * before a pointer you dereference that pointer which, in simple terms, gives you the object the pointer is pointing to. But as Mooing Duck said if you don't understand this you should avoid the new keyword all together.
Edit: to answer what it means? it means you allocate a board object then dereference it and save a new copy in your variable gameBoard. Essentially giving you two copies of the Board object.
new board(givenX,givenY,givenMineCount); in a nutshell, performs two things: creates a board object in memory and returns the address where it was created.
In your second statement, gameBoard is a stack variable that holds a board object. As I mentioned before, the new returns an address and by using the * operator, you're basically "interpreting" (the actual technical term is dereferencing) the address as a board. That said, doing this seems to be making a copy and assigning it to boardGame and leave lingering in memory what was created with new.
I'm new to c++, but I think extra details are missing here for beginners like me and like the asker.
Note: This answer contains details for newbies like me.. advanced c++ developers may find this post somewhat confusing!
Lazy? tl;dr at the end
Does always creating and object with *new creates two copies of objects? (one will never ever be deleted)
Lets check this out:
As explained by others, the *new is just a shortcut to new in one statement and then dereference it with the asterisk operator (*)
Consider the following struct that holds a single number:
struct myStruct
{
public:
myStruct() { innerNumber = 0; }
myStruct(uint16_t num) {
innerNumber = num;
}
uint16_t innerNumber;
};
Lets create a SINGLE object, and dereference it MULTIPLE times:
myStruct* obj = new myStruct();
myStruct obj1 = *obj;
myStruct obj2 = *obj;
myStruct obj3 = *obj;
obj1.innerNumber = 1;
obj2.innerNumber = 2;
obj3.innerNumber = 3;
printf("%d-%d-%d\n", obj1.innerNumber, obj2.innerNumber, obj3.innerNumber);
prints: 1-2-3
Pretty cool =] (and dangerous)
So, if we get it correctly, it is ALWAYS a bad idea to use *new as already mentioned here, it will always cause a memory leak!!
lets see it in action:
while (true) {
myStruct& inner = *new myStruct();
delete &inner;
}
That code should:
enter an infinite while loop
allocate a new myStruct object
dereference it (causing it to be copied!)
delete the copy only
Or in shortly: A MEMORY LEAK
Well, I'm running this, and the memory isn't increasing!
*new is GOOD when creating a reference. You can see that I defined
a ref type by the & operator (myStruct& inner)
Another problem that may arise (and is general for references) is that:
// Create a reference
myStruct& inner = *new myStruct();
inner.innerNumber = 0;
// WHAT WILL HAPPEN HERE?
myStruct whatAmI1 = inner;
myStruct whatAmI2 = inner;
whatAmI1.innerNumber = 1;
whatAmI2.innerNumber = 2;
printf("Original: %d Copies: %d-%d\n", inner.innerNumber, whatAmI1.innerNumber, whatAmI2.innerNumber);
prints: Original: 0 Copies: 1-2
dangerous!
TL;DR
*new is bad for creating value types
*new is good for creating reference type
Be careful when assigning a reference type to a value variable, it
makes a copy
To avoid keep having to use -> and instead work directly with the object, is it acceptable practice to do:
obj x = *(new obj(...));
...
delete &obj;
This is not just poor practice, but:
Leaking memory (most likely, unless you are using some pattern that is not visible from the code you provided), since obj will store a copy of the original object created by the new expression, and the pointer to that object returned by new is lost;
Most importantly, undefined behavior, since you are passing to delete a pointer to an object that was not allocated with new. Per paragraph 5.3.5/2 of the C++11 Standard:
[...] In the first alternative (delete object), the value of the operand of delete may be a null pointer
value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8)
representing a base class of such an object (Clause 10). If not, the behavior is undefined.
No, and in fact this leads to a leak. x is copy initialized, so the original object pointed to by new obj is lost.
Just use
obj x(...);
No need for dynamic allocation. Or
obj x = obj(...);
if you must (doubt it).
Certainly not; that copies the dynamic object to an automatic variable, loses the only pointer to it, and then attempts to delete the automatic copy. You've got a memory leak and an invalid deletion.
Much better would be to use an automatic variable in the first place:
obj x(...);
...
// no need to delete anything
or, if it really must be dynamic for some reason (because it's too big for the stack, or you don't always want to destroy it here), then use a smart pointer, and a reference if you really don't like ->
std::unique_ptr<obj> p(new obj(...));
obj & x = *p;
...
// still no need to delete anything
Changing your x into a reference would be valid (as long as you're careful that exceptions, early function returns, etc. won't cause a leak), but would cause howls of confusion among anyone unfortunate enough to have to maintain it.
You cannot delete your object properly if you do it like that.
Implicitly you do the following.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A v(*p);
//...
delete &v; // &v != p and v is not constructed via new!
return 0;
}
If you want to work with an object-like-syntax you can bind a reference to the object.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A & r = *p;
int i = r.test();
delete p;
return 0;
}
If you delete your object through the same pointer, there will be no leak.
To avoid keep having to use -> and instead work directly with the object, is it acceptable practice to do:
obj x = *(new obj(...));
...
delete &obj;
This is not just poor practice, but:
Leaking memory (most likely, unless you are using some pattern that is not visible from the code you provided), since obj will store a copy of the original object created by the new expression, and the pointer to that object returned by new is lost;
Most importantly, undefined behavior, since you are passing to delete a pointer to an object that was not allocated with new. Per paragraph 5.3.5/2 of the C++11 Standard:
[...] In the first alternative (delete object), the value of the operand of delete may be a null pointer
value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8)
representing a base class of such an object (Clause 10). If not, the behavior is undefined.
No, and in fact this leads to a leak. x is copy initialized, so the original object pointed to by new obj is lost.
Just use
obj x(...);
No need for dynamic allocation. Or
obj x = obj(...);
if you must (doubt it).
Certainly not; that copies the dynamic object to an automatic variable, loses the only pointer to it, and then attempts to delete the automatic copy. You've got a memory leak and an invalid deletion.
Much better would be to use an automatic variable in the first place:
obj x(...);
...
// no need to delete anything
or, if it really must be dynamic for some reason (because it's too big for the stack, or you don't always want to destroy it here), then use a smart pointer, and a reference if you really don't like ->
std::unique_ptr<obj> p(new obj(...));
obj & x = *p;
...
// still no need to delete anything
Changing your x into a reference would be valid (as long as you're careful that exceptions, early function returns, etc. won't cause a leak), but would cause howls of confusion among anyone unfortunate enough to have to maintain it.
You cannot delete your object properly if you do it like that.
Implicitly you do the following.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A v(*p);
//...
delete &v; // &v != p and v is not constructed via new!
return 0;
}
If you want to work with an object-like-syntax you can bind a reference to the object.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A & r = *p;
int i = r.test();
delete p;
return 0;
}
If you delete your object through the same pointer, there will be no leak.
I know that I can't get a reference of a local var. such as:
int& func1()
{
int i;
i = 1;
return i;
}
And I know that this is correct, but I have to delete it after calling func2()
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int *p = func2();
cout << *p << endl;
delete p;
return 0;
}
If the function is like this:
MyClass MyFunction()
{
return new MyClass;
}
MyClass's whole definition is:
class MyClass
{
public:
MyClass() : num(1){}
MyClass(MyClass*) : num(10){}
int num;
};
Will this cause memory leak?
How should I avoid it?
the function returns an object not a pointer, so how can I delete it?
PS: the code comes from the book "Ruminations on C++" Chapter 10.
the original code is:
Picture frame(const Pictrue& pic)
{
// Picture has a constructor Picture(*P_Node)
// Frame_Pic derives from P_Node
// So the constructor Picture(*P_Node) will implicitly convert Frame_Pic to Picture.
return new Frame_Pic(pic);
}
MyClass MyFunction()
{
return new MyClass;
}
This is actually wrong.you are returning a pointer .
so it should be
MyClass* MyFunction()
if your function is as i mentioned above and if you are not deleting it after using it.it will leak memory.
How should I avoid it? the function returns an object not a pointer, so how can I delete it?
that is a compilation error.so the point of deleting it will not rise
If you delete the pointer returned from the funciton there is no memory leak. However this is error prone since it means that every client of the function must know that it should delete the return value. It's much better style to use a smart pointer (either shared_ptr or unique_ptr according to semantics).
The same goes to the Picture example. If this object correctly manages its resources (i.e. deletes in the destructor and has a good copy constructor and operator= (in accordance with the Rule of Three), then there is no memory leak.
With your updated MyClass that has the pointer constructor, I suppose you should write:
MyClass MyFunction() {
MyClass *ptr = new MyClass;
MyClass retval(ptr);
delete ptr; // the dynamically-allocated object isn't needed any more
return retval;
}
That happens to be exception-safe, since the constructor of MyClass can't throw, but as a general rule you really shouldn't ever call new without putting the result straight into a smart pointer:
MyClass MyFunction() {
std::unique_ptr<MyClass>(new MyClass);
return MyClass(ptr);
}
It's a fairly absurd situation anyway - if you're going to return by value, there's no reason to call new at all:
MyClass MyFunction() {
MyClass tmpvalue;
return &tmpvalue; // doesn't actually return the pointer, just an object
// constructed from it
}
And since the value of the pointer isn't even used by the pointer constructor, you could just as well write:
MyClass MyFunction() {
return 0; // returns an object constructed from a null pointer
}
In the original code your quote from the book, I guess that the class Picture has a data member of type P_Node*, in which it stores the pointer value, and calls delete on that pointer in its destructor. Hopefully the author also does something about the copy constructor and copy assignment operator of Picture, to prevent a double-free after the copy. I don't have the book, so I can't check my guess, but the code for Picture should show how it's done.
[Edit: oh, that's one of the books by Koenig and Moo. They are (more than) competent, so pretty certainly their Picture class handles the resource correctly. If it doesn't, it's because it's a deliberate example of Doing It Wrong.]
It's the same as your "func2" example. who ever call "frame" need to free the returning Picture in the end.
MyClass MyFunction()
{
return new MyClass;
}
is incorrect, because operator new returns a pointer to MyClass, but your function returns MyClass, not MyClass*
A simple check would be this:
If you're using N number of new in your program, then you've to use N number of compatible1 delete in your program to avoid memory leak2.
So are you doing that? Yes, in the first case (in which you're doing new int) you're doint that. There is no memory leak.
And rest of the post isn't clear enough to me!
1. By compatible delete, I mean if you're using new in the form of ptr = new T[M], then the compatible delete should be of the form of delete []ptr. Similarly, delete ptr is compatible with ptr = new T.
2. Of course, if you're using some smart pointers, then you don't have to use delete explictly.
I've just read the new operator explanation on the cplusplus.com. The page gives an example to demonstrate four different ways of using new operator as following:
// operator new example
#include <iostream>
#include <new>
using namespace std;
struct myclass {myclass() {cout <<"myclass constructed\n";}};
int main () {
int * p1 = new int;
// same as:
// int * p1 = (int*) operator new (sizeof(int));
int * p2 = new (nothrow) int;
// same as:
// int * p2 = (int*) operator new (sizeof(int),nothrow);
myclass * p3 = (myclass*) operator new (sizeof(myclass));
// (!) not the same as:
// myclass * p3 = new myclass;
// (constructor not called by function call, even for non-POD types)
new (p3) myclass; // calls constructor
// same as:
// operator new (sizeof(myclass),p3)
return 0;
}
My questions are:
What is the best practice of using
new operator?
Is myclass* p3 = new myclass equivalent to myclass* p3 = new myclass()?
Because they have different purposes. If you didn't want new to throw std::bad_alloc on failure, you would use nothrow. If you wanted to allocate your objects in existing storage, you would use placement new … if you want raw, uninitialized memory, you would invoke operator new directly and cast the result to the target type.
The plain standard usage of new in 99% of all cases is MyClass* c = new MyClass();
To your second question: the new Object() vs. new Object forms are not generally equal. See this question and the responses for the details. But that really is nitpicking. Usually they are equivalent, but to be on the safe side always pick new Object(); Note that, in this particular sample they are equal because MyClass doesn't have any members, so strictly speaking the answer to your question is yes.
1) Several of these are used only in specific, unusual situations. The plain old traditional one is best, most of the time anyway:
X * x = new X();
2) Yes, they are. If the constructor has no arguments, the parentheses are optional. If you're declaring an automatic variable -- i.e.,
X x;
then you must omit the parentheses, or it's a function declaration! As a result, many people will tell you to omit them in the new expression as well. That's a good practice, I think, but I'm just used to including them.
Rather than "best practice", you need them in different situations. For example, most people just want to call new x() to allocate some memory and create the object. However, sometimes you're in situations where you don't want an exception thrown in case new fails, so you call new (nothrow) instead to get a null back.
If you already have some memory allocated but need to create an object, you use "placement new" by calling new (p3) x.
In the rare case where you need to use a class's memory allocator but not actually create an object, you use the (myclass*) operator new (sizeof(myclass)) syntax.
Here are my recommendations:
Prefer not to use new; pass by
reference when possible. (Avoids memory leaks).
Use operator new: x = new X(); // Remember to use delete
Prefer std::vector to array new:
x = new X()[quantity]; // Remember to use delete []
Don't use placement new unless
you absolutely know the reasons.
In general, placement new is used to allocate from specific addresses or a special memory pool. This is an advanced topic.