int main(){
int *a = new int[5];
int *b = new int[10];
int *c;
for (int i = 0; i < 5; ++i){
a[i] = i * i;
}
for (int i = 0; i < 10; ++i){
b[i] = 50;
}
c = a;
a = b;
delete[]b;
delete[]c;
return 0;
}
After the execution of code above, has the memory a originally pointed to been freed?
If not, how to free correctly?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pointer a has to be reserved for other uses, so it is prohibited to delete a directly.
the purpose of this code is to access the memory belonging to b originally via a and free the memory a used to possess correctly.
Yes, the memory is freed. However, be very careful when changing what a pointer points to because it can easily lead to memory leak.
Yes it has. Pointer are normal variables that happen to contain addresses. Since a is assigned to c. Your first allocation is freed.
It is freed.
Because after c = a;, c holds the memory address of a originally pointed to. And you have freed c by delete [] c;.
// Assume originally a -> 1, b -> 2
c = a; // Now a -> 1, b -> 2, c -> 1
a = b; // Now a -> 2, b -> 2, c -> 1
You can free a or b, at least one of them, they point to the same memory block. You must free c.
After the execution of code above, has the memory "a" originally
pointed to been freed?
Yes, the memory is freed. As c=a, delete [] c; clears the memory of a.
However, you don't need *c to clear memory, just directly delete a and b
delete[]a;
delete[]b;
UPDATE
As you have edited your answer and now it is more clear what you are trying to achieve,i.e. access memory pointed to by b via a but before that you want to free memory pointed to by a. So here's what you need to do:
1- First free the memory pointed to by a
delete []a;
2- Now point a to the memory location pointed to by b
a=b;
Now the memory location originally pointed to by a is cleared and a now points to where b is pointing.
Note: Keep in mind that now when you have both a and b pointing to the same memory location, if you use either delete []a or delete []b, memory location pointed to by both a and b will be cleared.
Imho a lot of confusion can be avoided when you think of delete as not acting on the pointer, but on the object it points to. It is not the pointer that is deleted, but the array. Take this example, which is actually very similar to yours:
struct Foo {
int id;
Foo(int i) : id(i) {}
};
Foo* a = new Foo(1);
Foo* b = new Foo(2);
Foo* c;
c = a;
delete c;
c = b;
delete c;
The only effect delete c; has on c is that we are not allowed to derefernce it afterwards, but what gets deleted is first the Foo object with id 1 and then the one with id 2.
Another way - you can to think about optimizations. Maybe you don't need to allocate memory here.
See this case
int a[5];
int b[10];
int func(int param) {
for (int i = 0; i < 5; ++i){
a[i] = i * i;
}
for (int i = 0; i < 10; ++i){
b[i] = 50;
}
}
int main(){
for (int i = 0; i < 10000; ++i){
func(i);
}
return 0;
}
You don't need to allocate/free memory per iteration. But if you have multithreading, it will be a bit more complicated.
Using similar method I greatly improved the speed of calculations in the project for science.
Your code should be clear for everybody. Think about who will be after you. If the choice between readability and speed - should choose readability.
Related
Here is my code
char * a()
{
char * c;
char b[10];
b[0] = 'h';
b[1] = 'i';
b[2] = '\0';
for (int i = 0; b[i] != '\0'; i++)
c[i] = b[i];
return c;
}
int main()
{
char * d;
d = a();
cout << d;
}
The problem is no output is being shown when it should have shown hi. Just wanted to know why this error occured.
"Edit": I finally realise it was due to not initialising the pointers. Pointer should always be initialised .
Example char * c= new char;
When you want an array you need to allocate space for the items. Just a pointer is not enough. Something like
char* c= new char[10]; //room for 10 chars
and be sure not to try indexes greater than 10-1=9. Accesing c[10] is undefined behaviour.
You can return that pointer (return c;). But don't forget to free the allocated memory when it isn't needed any more
d = a();
cout << d;
delete [] d; //free memory allocated with new d[...]
There are couple of errors in your program. Look that you create pointer of type char and then you do something like this:
c[i]
which will cause error. This is not what you want to do.
Also
you should not return pointer/reference to local variables. Local variables are destroyed when they leave scope (in your example b is destroyed at "return c;").
So when you create pointer to local object (notice that your variables are created on stack, not on heap) and return from function your pointer points to memory which is destroyed. It may worked it may not (undefined behaviour) but you should never do something like that.
I have a piece of code that deals with C++ array.
using namespace std;
#include <iostream>
int main(){
int *p;
p = new int[3];
for(int i = 0; i < 3; i++){
p[i] = i;
}
//delete[] p;
for(int i = 0;i <3; i++){
std::cout << *(p+i) << std::endl;
}
}
How does this code work? How does the memory location *(p+i) work? How is it different from using p[i]. What are the differences on the code if we uncomment the line delete[] p.
1) When you do this:
p = new int[3];
Now, p points to the first element of the dynamically allocated array.
When you do, *(p + i) will lead to simple pointer arithmetic. It will boil down to: value of (<address pointed by p> + <size of type pointed by p> * i) which is equivalent to doing p[i].
That's why it works.
2) In C++, unlike java, you have to explicitly clear the dynamically allocated memory using delete, as there is no GC in C++ (and will never be, as per Bjarne Stroustrup). Otherwise, the memory area will remain acquired for the application lifetime, thereby causing memory leak.
Suggestion:
Place your delete at the end of the program. Otherwise, the loop below it may give SIGSEGV.
Also, Avoid using new and delete as much as you can.
I have question regarding the array of pointers in the C++. I wonder if it's safe to do this:
int *a = new int[4];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
delete[] a; //release the memory
a = new int[6]; //re-construct with a new size.
a[0] = 5;
a[1] = 6;
a[2] = 7;
a[3] = 8;
a[4] = 9;
a[5] = 10;
Thank you for your time.
Depends on your usage. In this example:
int main() {
Your Code
}
It is safe, because after then end of main, all memory will be released by the OS. But if you do this:
int main() {
while (true) {
Your Code
}
}
You are generating a memory leak, because you are not releasing the memory after re-initializing it. You use more and more memory and will eventually cause a failed new[] (Stack Overflow).
You should delete every object created by new (and delete[] every array created by new[]).
int *a = new int[4];
a[0] = 1;
...
delete[] a; //release the memory
a = new int[6]; //re-construct with a new size.
...
delete[] a;
But overall the benefit of c++ in this case is RAII (Resource acquisition is initialization) types. This means you should be using provided c++ types like std::vector which handle memory creation and deletion in a good encapsulated way.
Yes is is. (If you delete a afterwards ;))
Yes that's fine. The rule is that every new[] needs a matching delete[] (just as every new needs a matching delete).
Although, if I were you, I'd use a std::vector<int>, and call its member function resize as necessary. (Then you are less likely to have memory issues: note well that you're missing a final delete[]).
I am learning classes in c++ so I try different things to get used to the classes. Here I am trying to pass a pointer to a class function:
class Pointerss{
int size;
public:
Pointerss(int);
void f();
int *a;
};
Pointerss::Pointerss(int siz){
size = siz;
}
void Pointerss::f(){
cout<<"Size is:"<<size<<"\n";
for (int i=0; i<size; ++i) {
cout<<"a is:"<<a[i]<<"\n";
}
}
int main() {
int size = 5;
Pointerss dd (size);
Pointerss * p = new Pointerss(size);
p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
p->a;
dd.f();
return 0;
}
So the "size" is initialized by a constructor and when "f()" is called the correct digit is printed. But when I assign "p" to "a" ("p->a") and then call "f()" some random numbers are printed. My computer prints :
Size is:5
a is:0
a is:0
a is:1
a is:0
a is:1606416856
Program ended with exit code: 0
what is the difference between "a" and "size" and what should I do to pass a pointer to a function?
Random numbers are printed because Pointerss::f dereferences dd.a which you never initialized. Dereferencing an uninitialized pointer results in undefined behaviour.
That's not the only bug you have. You also allocate memory for a single Pointerss object, which is pointed by p, but then proceed to construct objects in p[1..4] which point to unallocated memory. That also results in undefined behaviour.
Thirdly, you never deallocate the memory that you allocated with new.
Step 1 would be to understand pointers. When you make a int* you only reserve memory to store the pointer itself. You don't reserve memory for any int. So when you try to print the integers you just get random numbers (or perhaps a program crash).
So your class can't hold any integers. You need to change it so that you reserve memory in the constructor and release it in the destructor.
class Pointerss{
int size;
public:
Pointerss(int);
~Pointerss();
void f();
int *a;
};
Pointerss::Pointerss(int siz){
size = siz;
a = new int[size]; // Reserve memory for size integers
// Do some initialization if needed, e.g.
for (int i=0; i < size; i++) a[i] = i;
}
Pointerss::~Pointerss(){
delete[] a; // Release the memory again
}
void Pointerss::f(){
cout<<"Size is:"<<size<<"\n";
for (int i=0; i<size; ++i) {
cout<<"a is:"<<a[i]<<"\n";
}
}
Further you can't make a single pointer to an instance of the class, i.e.
Pointerss * p = new Pointerss(size);
and then use it like
p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
because that is operating on 5 different instances.
Finally the code:
p->a;
does nothing!
You could do
p->a[0] = 5;
but it is unclear what you are trying to do.
Notice that dd and p are refering to two different instances of your class so changing something inside *p doesn't change dd at all.
If you had done:
Pointerss *p = ⅆ
then *p and dd would be the same instance.
This is a simple question and I'm kind of a beginner, but I would just like to confirm this.
Say I have a class object int * data, which is pointing to an array of 5 ints. Say I have a function that would replace data with 5 arguments, as illustrated below.
void replaceData(int a, int b, int c, int d, int e){
int * temp = new int[5];
temp[0] = a;
temp[1] = b;
temp[2] = c;
temp[3] = d;
temp[4] = e;
data = temp;
}
I am concerned that this would cause a memory leak, because if data already had 5 ints in there, they would still be floating around. I am tempted to change it in the following way to avoid this:
void replaceData(int a, int b, int c, int d, int e){
int * temp = new int[5];
temp[0] = a;
temp[1] = b;
temp[2] = c;
temp[3] = d;
temp[4] = e;
delete data; //would this prevent a memory leak?
data = temp;
temp = 0;
}
Thank you very much for your input!
If data was allocated in the same way as you are allocating temp then yes, you would need to free the old array first before modifying the pointer - otherwise you will have a memory leak.
Note that if you allocate an array (new int[5]) then you must free the array like this:
delete[] data;
Also, it's much better to use an STL container like std::vector rather than allocating arrays manually, as all the memory management is handled for you.
Almost.
The delete operator is for pointers to single objects. You need to do delete[] data for this to work. Zeroing the temp pointer at the end doesn't make a difference.
Your code would be correct if it were delete[] instead of delete. If the size is hardcoded though, there's no point in using a dynamically allocated array (at least not in this context). Just use an int temp[5];.
Better yet, just use vectors. Then it's a simple call to std::swap.