Frage

I know memory that has been dynamically allocated and using the heap needs to be manually deleted using delete. Is this also the case if a dynamic object is created in a class function that will go out of scope? Here is a snippet.

    Fraction* Fraction::add(const Fraction* fr) const{ 
      int gcd;
      Fraction* temp;

      gcd = gcdRecur(num * fr->denom + fr->num * denom, 
                     denom * fr->denom);

      temp = new Fraction((num * fr->denom + fr->num * denom) / gcd, 
                          (denom * fr->denom) / gcd);

      return temp;
   }

In this case, temp is a pointer to a dynamic object of type Fraction using 'new' (right?). If I am returning this pointer to wherever the class function 'add' was called, will I need to delete the local pointer 'temp'? If so, how can I accomplish this?

EDIT: My (wrong) interpretation of using new in this class member is because the Fraction objects are being instantiated through pointers to Fractions (like so):

    int main() {
      menu()
      return 0;
    }

    void menu() {
      Fraction* fr1 = 0;
      Fraction* fr2 = 0;
      Fraction* fr3 = 0;
      // ... user chooses to initialize, so fr1, fr2, fr3 no longer null

      // ... user chooses to add. call submenu, pass fr1, fr2, fr3 by POINTERS?
      addMenu(fr1, fr2, &fr3);
    }

Looks bad... Here's the header for the addMenu:

     void addMenu(const FractionTeddyD*, const FractionTeddyD*, FractionTeddyD**);

EDIT #2: Solved without using 'new'. T

War es hilfreich?

Lösung

It does indeed need to be deleted, otherwise the memory will be leaked. You can't delete it locally, since the caller needs to use it after the function returns. The caller will have to delete it once it's no longer needed. Obviously, this is error-prone, which is why you should always use RAII to manage dynamic resources.

In this case, you should change the return type to a smart pointer like std::unique_ptr<Fraction>.

On the other hand, why are you using new here at all? Returning a value would be simpler and almost certainly faster.

Andere Tipps

You can use smart pointers such as std::unique_ptr or std::shared_ptr.

 std::unique_ptr<Fraction> Fraction::add(...) const { 

      ...

      std::unique_ptr<Fraction> temp (new Fraction(...));

      return temp;
  }

And you can get rid of worrying about deleting memory.

You will need to delete the memory as soon as you stop using it. The memory won't be released for you, unless your compiler has a built-in memory clearing system, and embeds it in your *.exe file.

On a side note: you probably don't want to allocate new memory in a add function. Try reading about overloading operators. When you look the term up, you'll probabl notice operator + usually returns a reference to an instance of the class. And I think that would be probably the better soulution in your problem.

If you really need the pointer, and you don't want to be bothered by thinking when to delete it, there are many classes that store smart pointers like std::shared_ptr (reference)

Pointers in c++ are passed by value, meaning you can delete the object anywhere you have the pointer (as long as it hasn't already been deleted). Since they essentially just store an address this is fine because when delete is called it knows where and how to free the memory.

In your case you would delete it outside the function otherwise there is no point in returning it. To avoid having to manage the memory yourself you should actually be using an std::unique_ptr

std::unique_ptr<Fraction> Fraction::add(const Fraction* fr) const{ 
  int gcd;

  gcd = gcdRecur(num * fr->denom + fr->num * denom, 
                 denom * fr->denom);

  std::unique_ptr<Fraction> ptr(new Fraction((num * fr->denom + fr->num * denom) / gcd, 
                      (denom * fr->denom) / gcd));

  return ptr;

}

Using this style will save you many headaches and is now considered idiomatic in c++. The parameter fr could also be passed as a unique_ptr, to adopt this style of coding you will also want to understand std::shared_ptr which represents a ptr that does not have unique ownership (more than one can exist).

However the real problem is when you create an object on the heap without saving the pointer with the address of the object. Then that object is lost and cannot be freed.

Your design of the likely tiny class fraction is probably no good.

Having:

class Fraction {
    public:
    int numerator;
    int denominator;
};

you could pass by reference and return by value:

Fraction Fraction::add(const Fraction& fr) const;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top