clarification for understanding new and delete

Would anyone mind just checking my code to see if there are any memory leaks?
I have been learning about new and delete and am very interested in using those keywords but I have trouble knowing when to use delete when other functions and classes are involved.

Also, if there are any thought processes or ways of thinking that would help me understand new and delete better, please share. Thanks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include "Box.h"

void objDestroyer(Box* ptr);
float func(Box* ptr, int m);
float func(Box *ptr);
int main()
{
    Box box1(4.5, 6.7, 7.6);
    Box *ptr, *ptr2,*ptr3;
    ptr = &box1;
    ptr2 = new Box(6.0,5.0,5.0);//in junction with delete
    ptr3 = new Box(0.8,0.8,0.8);

    std::cout << "Volume: " << ptr->getVolume() << std::endl;
    std::cout << "Width from function: " << func(ptr) << std::endl;
    func(ptr2, 2);
    std::cout << "Width after pass through function: " << ptr2->getWidth();
    delete ptr2; //is this good or am I causing a leak?
    objDestroyer(ptr3); //is this valid?
    return 0;
}

float func(Box* ptr)
{
    float temp;
    temp = ptr->getWidth();
    return temp;
}
float func(Box* ptr, int m)
{
     ptr->addWidth(ptr->getWidth() * 2);
}
void objDestroyer(Box* ptr)
{
delete ptr;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Box.h
#ifndef BOX_H_INCLUDED
#define BOX_H_INCLUDED

class Box
{
    public:
        Box(float width, float height, float length);
        float getVolume(){ return (widthC * heightC * lengthC);}
        float getWidth(){return widthC;}
        void addWidth(float addit);
    private:
        float widthC;
        float heightC;
        float lengthC;
};

#endif // BOX_H_INCLUDED 



1
2
3
4
5
6
7
8
9
10
11
12
13
//Box.cpp
#include "Box.h"
Box::Box(float width, float height, float length)
{
    widthC = width;
    heightC = height;
    lengthC = length;
}
void Box::addWidth(float addit)
{
    widthC += addit;
}
Last edited on
Each new should be paired with delete and new[] with delete[]. You have 2 new calls and 2 delete calls. You do not have any leaks, nor you ahve double delete problem.

However function:
1
2
3
4
float func(Box* ptr, int m)
{
     ptr->addWidth(ptr->getWidth() * 2);
}
is declared as returning float but does not return anything. This is undefined behavior. Change return type to void or really return something

Also:
1
2
3
4
5
6
float func(Box* ptr)
{
    float temp;
    temp = return ptr->getWidth();
    return temp;
}
@MiiNiPaa thanks, I usually do pair them together, but I find it confusing to know at what time it is good to use them, I think I need to learn scope better because maybe that is the source of my confusion.

Also, thanks for pointing that out with both functions, noob mistakes.
:)!

1
2
3
4
    delete ptr2; //is this good or am I causing a leak?
    objDestroyer(ptr3); //is this valid?

    return 0;

These are valid. However, the standard now has managed pointers. See http://www.cplusplus.com/reference/memory/

http://timoch.com/blog/2013/04/std-unique_ptr-semantic/
Since C++14, your "interesting keywords" are needed even less: http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <memory>

float func( const Box & ptr )
{
    return ptr.getWidth();
}

void func( Box & ptr, int m )
{
     ptr.addWidth( ptr.getWidth() * 2 );
}

int main()
{
    Box box1(4.5, 6.7, 7.6);
    Box *ptr;
    ptr = &box1;
    auto ptr2 = std::make_unique<Box>(6.0,5.0,5.0);

    std::cout << "Volume: " << ptr->getVolume() << std::endl;
    std::cout << "Width from function: " << func(*ptr) << std::endl;
    func( *ptr2, 2 );
    std::cout << "Width after pass through function: " << ptr2->getWidth();

    return 0; // the destructor of ptr2 will delete the Box that it owns
}
Last edited on
@keskiverto thanks, what use does auto-pointers have as opposed to declaring variables on the stack? I mean, the point of pointers is mostly for run-time functionality right? Or specifically the point of new and delete?

Also, the reason I want to decide when to delete is because I want to create a sort of rpg cmd game where the Player can equip a weapon, however, I want the weapon to have a specific durability so that at the end of it's durability the object is destroyed. I've looked online but I can't seem to find any explanation to how to delete an object after it's been created besides scope and new and delete.

1
2
3
4
5
Weapon ptr = new Weapon; //pointer to weapon object
if(durability <= 0) //if weapon durability has hit 0
{
delete ptr; //deletes that object?
}


Is this code valid code?
Would this be a good method to get rid of an object that I no longer want to be in existence?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
Weapon *ptr = new Weapon; //pointer to weapon object
if(durability <= 0) //if weapon durability has hit 0
{
delete ptr; //deletes that object
ptr = NULL;
}
//...
if(!ptr && durability<=0) // previous if may not be true
{
delete ptr; //deletes that object
ptr = NULL;
}
what use does auto-pointers have as opposed to declaring variables on the stack?

I should have written that line 18 as:
std::unique_ptr<Box> ptr2 = std::make_unique<Box>(6.0,5.0,5.0);

Yes, both ptr and ptr2 are on the stack. Both cease to exist when the scope ends. The thing is that you might exit the scope from multiple points:
1
2
3
4
5
6
7
8
9
10
int foo() {
  Bar bar = new ...;
  // use bar
  if ( cond ) {
    // use bar
    return 0;
  }
  // use bar
  return 1;
}

If Bar is a raw pointer, then you should deallocate before line 9 and before line 6.
If Bar is a "smart pointer", then its destructor can call delete on every exit point.

Smart pointers can transfer ownership, so the stack variable that originally points to the dynamically allocated object does not have to be the one that actually deletes it.

Then there is the std::shared_ptr. Multiple pointers can point to same object. If they are shared_ptr, they know each other and the lifetime of the object is until the last one of these pointer is destroyed.

Pointers (both raw and smart) can be either valid or invalid. One should not dereference an invalid pointer. One should thus test pointer before using it. anup30 assigns 0 to ptr to show that it is invalid. If you don't do that after delete, and test the pointer later, then it still has a valid looking address even though memory in that location has already been deallocated.


No munchkin hero is happy with just one blade!
1
2
3
4
5
6
7
8
9
10
11
12
std::vector<Weapon> belt;
belt.emplace_back( "Vorbal blade" );
belt.emplace_back( "Mjölnir" );
belt.emplace_back( "daffodils" );

if ( 0 < belt.size() ) // I have weapons
{
  if ( belt.begin()->isBroken() ) // first weapon has turned to garbage
  {
    belt.erase( belt.begin() ); // deletes the first weapon
  }
}
Thanks @keskiverto! :D
Also, thanks @anup30 for the alternative.
Topic archived. No new replies allowed.