Right now I feel fairly unlearned with dynamically allocating memory... even after doing so several times and doing projects that require one to dynamically allocate memory for classes and primitive types.

Basically, how does one research allocation for different scenarios such as...

#include <cstdlib>
#include <iostream>

using namespace std;

class Other
{
};

class MyClass
{
     public:
           int amount;
           Other **other1, *other2;           

           MyClass(Other *ot, int size)
           {
                   amount = size;
                   other2 = new Other[size];
                   other1 = new Other*[size];
                   
                   for(int i = 0; i < size; i++)
                   {
                             other1[i] = new Other[1];
                             other1[i] = &ot[i];
                             other2[i] = ot[i];
                   }
           }
           ~MyClass()
            {
                    for(int i = 0; i < amount; i++)
                    {
                             delete other1[i];
                    }

                    delete other1;
                    delete other2;
            }
};

int main(int argc, char *argv[])
{
    
    Other o[5];
    
    MyClass mc (o, 5);
    
    mc.~MyClass();
    
    cin.get();
    return 0;
}

Is the above correct?

I've been looking through various sites for examples of how to properly deallocate memory or assign objects to pointers with allocated memory and the usual examples only include 1 pointer.

Edit: Also, what should I do when I don't have a primary void constructor when allocating memory for that object for a double pointer? What then?

The code you oposted has a huge memory leak. Line 24 allocates some memory then line 25 tosses the pointer away and uses it for something else. One of those two lines needs to be deleted. My preference is to keep line 24 and delete line 25 so that the class has complete control over all its data.

Since MyClass does not own the memory for Other1 and Other2 (see lines 25 and 26) the MyClass destructor will most probably cause a core dump or some other nasy abnormal segmentation fault. You can not delete[] something you did not allocate with the new operator.

line 48: you compiler will give you an error on that line because you do not call destructors explicitly.

Emphasizing line #48, the mc object is on stack (i.e. not allocated by new), so when it goes out of scope, its destructor gets called automatically. Generally you don't call destructors, those get called via delete or automatically in case of stack objects.

> Basically, how does one research allocation for different scenarios
One learns the basics of dynamic memory and applies it in an ad hoc manner with every new scenario. Eventually you'll have seen scenarios before and the effort you put into doing it the first time will make subsequent times easier. Edward hasn't found a better way. :(

> the usual examples only include 1 pointer
Pointers are very uniform. Adding another pointer or another level of indirection doesn't change the principles, even if it does make the code more complex really really fast. ;)

The code you oposted has a huge memory leak. Line 24 allocates some memory then line 25 tosses the pointer away and uses it for something else. One of those two lines needs to be deleted. My preference is to keep line 24 and delete line 25 so that the class has complete control over all its data.

Since MyClass does not own the memory for Other1 and Other2 (see lines 25 and 26) the MyClass destructor will most probably cause a core dump or some other nasy abnormal segmentation fault. You can not delete[] something you did not allocate with the new operator.

line 48: you compiler will give you an error on that line because you do not call destructors explicitly.

Thanks everyone for your responses. I didn't realize my projects were causing such incredibly memory leaks. I'll look out for them.

And AD, my experience with allocating memory for double pointer has been the following--

--Whenever I declare a double pointer (for a class for example) and don't allocate memory for the pointers, my program shuts down on me because I'm supposedly trying to assign data to memory that I shouldn't have access to...

Which makes no sense because I thought that you could assign the initial value of the pointer to a valid reference regardless of whether you've allocated memory for it or not... This is the most confusing thing for me from switching from java to C++ because it feels like there are some inconsistencies with memory allocation.

For example, if I want a pointer to pointers in the following fashion...

int **intDPtr, int arr[5] = {1, 2, 3, 4, 5}, int arr2[5] = {6, 7, 8, 9, 10}, int *ptr1 = arr, int* ptr2 = arr2;

I supposedly cannot assign intDptr[0] with arr then intDptr[1] with arr2 without initially allocating memory for these "pointer objects" in the double pointer.

What I have concluded (which I know I may be wrong) is that I must be assigning a copy of the address to the other pointers in the double pointer which is why the compiler has an issue with pointers being allocated to the double pointer. I suppose I have to do something like--

int Dptr = new int*[pointerAmount];

but afterwards do I really need to allocate blocks of memory for the amount of pointers the double pointer is pointing to, if the pointer already handles memory initialization on its own or do I need to assign a certain amount of space for each pointer since ill be copying the address again?

I'm confused honestly...

I have my project attached, which I'm sure has a ton of memory leaks. The reason I'm asking these questions is because I've encountered these problems numerous times and I know I'm only learning bad programming by trying to code around the problem without actually solving it.

Radical Edwards and AD I will definitely look into better solutions for maintaining memory management. And RE it's really a damn shame that it takes hardcore trial and error to get this down but I definitely won't give up on it.

If any of you have the time please tell me what I did wrong in my project (in terms of memory management - I'm aware of some of the access issues that I'm trying to tweak but I have some sketches drawn out for what I want to do... it's the memory management that is the biggest issue).

Attachments
#pragma once
#include <iomanip>
#include "string_lib.h"


class Game_Object; //a component that can be added to the game
class _Manipulator; //a manipulator that has the right to manipulate other engine_parts
class Engine_Part; //a peice of the engine - performs independant functionality
class Engine; //simply a collection of Engine_Parts, but can be treated as a _Manipulator
class Creature; //abstract class that defines "living" creatures in the game
class PlayableCharacter; //for controllable characters
class NonPlayableCharacter; //for enemies and npcs
class Parameters; //holds information for a Game_Object
class Inventory; //Inventory for all living creatures in the game
class Item; //Items that are visible in the game
class Selector; //Works like an engine, but the objects stored are selected before, or during run-time

/**
LESSON! DO NOT USE MALLOC ON NON-PRIMITIVE TYPES!!! USE MALLOC ONLY FOR PRIMITIVES!

MALLOC MEANS THAT THE OBJECTS CONSTRUCTOR WONT BE RUN AND THAT SPACE WILL
BE ALLOCATED FOR THE OBJECT! NEW ENSURES THE CONSTRUCTOR WILL RUN AND DELETE ENSURES DESTRUCTOR WILL RUN!
*/
class Parameters{
       friend class PlayableCharacter;
       friend class NonPlayableCharacter;
       
       protected:
               struct MAX_STATS{
                    public:
                               
                      int HP_M, MP_M, INCLOSE_M, EXP_TNL;
                      
                      MAX_STATS(){HP_M = 27, MP_M = 10, INCLOSE_M = 13, EXP_TNL = 250;};
                      MAX_STATS(int hp, int mp, int inclose, int exp){
                          HP_M = hp; MP_M = mp; INCLOSE_M = inclose; EXP_TNL = exp;          
                      }
                      
                      int &operator[] (int arg){
                          switch(arg){
                              case 0:
                                     return HP_M;
                              case 1:
                                     return MP_M;
                              case 2:
                                     return INCLOSE_M;
                              case 3:
                                     return EXP_TNL;
                              default:
                                      return HP_M;       
                          }
                      }
                      
                      char *operator[] (double arg){
                          int value = static_cast<int>(arg);
                          switch(value){
                              case 0:
                                     return "MAX HP";
                              case 1:
                                     return "MAX MP";
                              case 2:
                                     return "INCLOSE PEAK";
                              case 3:
                                     return "EXP to next LVL";
                              default:
                                      return "MAX HP";       
                          }
                      }                      
               } ms;
               
               struct CURRENT_STATS{
                  public:
                         
                      int HP, MP, INCLOSE, EXP;
                      
                      CURRENT_STATS(){HP = 27, MP = 10, INCLOSE = 0, EXP = 0;};
                      CURRENT_STATS(int hp, int mp, int inclose, int exp){
                          HP = hp; MP = mp; INCLOSE = inclose; EXP = exp;          
                      }                     
                      
                      int &operator[] (int arg){
                          switch(arg){
                              case 0:
                                     return HP;
                              case 1:
                                     return MP;
                              case 2:
                                     return INCLOSE;
                              case 3:
                                     return EXP;
                              default:
                                      return HP;       
                          }
                      }
                      
                      char *operator[] (double arg){
                          int value = static_cast<int>(arg);
                          switch(value){
                              case 0:
                                     return "HP";
                              case 1:
                                     return "MP";
                              case 2:
                                     return "INCLOSE";
                              case 3:
                                     return "EXP";
                              default:
                                      return "HP";       
                          }
                      }                      
               } cs;
               
               struct PRIMARY_STATS{
                  public:
                         
                      int LEVEL, STR, ACC, DODGE, INT, ARMOR, SPI_ARM;
                      
                      PRIMARY_STATS(){LEVEL = 1, STR = 5, ACC = 3, DODGE = 1, INT = 2, ARMOR = 10, SPI_ARM = 5;};
                      PRIMARY_STATS(int lvl, int str, int acc, int dod, int magi, int arm, int spi){
                            LEVEL = lvl; STR = str; ACC = acc; DODGE = dod; INT = magi; ARMOR = arm;
                            SPI_ARM = spi;         
                      }
                      
                      int &operator[] (int arg){
                          switch(arg){
                              case 0:
                                     return LEVEL;
                              case 1:
                                     return STR;
                              case 2:
                                     return ACC;
                              case 3:
                                     return DODGE;
                              case 4:
                                     return INT;
                              case 5:
                                     return ARMOR;
                              case 6:
                                     return SPI_ARM;
                              default:
                                      return LEVEL;       
                          }
                      }
                      
                      char *operator[] (double arg){
                          int value = static_cast<int>(arg);
                          switch(value){
                              case 0:
                                     return "LVL";
                              case 1:
                                     return "STR";
                              case 2:
                                     return "ACC";
                              case 3:
                                     return "DOD";
                              case 4:
                                     return "INT";
                              case 5:
                                     return "ARM";
                              case 6:
                                     return "SPI";
                              default:
                                      return "LVL";       
                          }
                      }                                            
               } ps;
               
       public:
              std::ostream &setParametersVisible(bool condition, int streamRowPosition, int streamColPosition){
                   //Code to manipulate how the parameters will appear on the screen...
                   return std::cout;           
              };
};

class Item{     
      friend class Inventory;
      friend class PlayableCharacter;
      
      private:
              char itemSymbol;
              Item(){itemSymbol = '_';};
              
      protected:
             Item(char c){itemSymbol = c;};
      
      public:
             virtual char getSymbol(){return itemSymbol;};
             bool operator== (Item &other){return itemSymbol == other.getSymbol();};
             bool operator== (char arg){return getSymbol() == arg;};          
};

class Inventory{
       private:
               Item **items, *temporary;
               int currentRowSize, currentColSize;
       
       protected:
                 Inventory(int &size){
                     if(size <= 1)
                        size = 1;
                     else if(size > 20)
                        size = 20;
                              
                     currentRowSize = currentColSize = size;
                     temporary = 0;
                      
                     items = new Item*[size]; 
                      
                     for(int i = 0; i < size; i++)
                        items[i] = new Item[size]; //use new for classes, and malloc for primitive types                    
                 };
       
       public:
              Inventory(){
                   items = new Item*[5];
                   temporary = 0;
                   
                   currentRowSize = 5;
                   currentColSize = 5;
                   
                   for(int i = 0; i < 5; i++){
                        items[i] = new Item[5];                     //use free and NOT delete when malloc
                      }                                             //Also since these are objects, use                                                 
              };                                                    //new/delete instead of malloc/free
              
              ~Inventory()
              {
                     for(int i = 0; i < currentRowSize; i++)
                          delete items[i];
                          
                     delete items;
                     
                     if(temporary != 0)
                          delete temporary;
              };
              
              void increaseSize(){
                   if( currentRowSize <= 9 && current
#include <cstdlib>
#include <iostream>
#include "GameCreator.h"
#include "string_lib.h"

using namespace std;

class A_Character : public PlayableCharacter{
      public:
             A_Character(char *name) : PlayableCharacter(name){
                    cout << "Creating Character: " << name << endl;     
             }
             
             A_Character(): PlayableCharacter("NameNotSet"){cout << "Creating Character: " << "NOTSET" << endl;};
             
             void setName(char *arg){objName = arg;};
};

class MyEnginePart : public Engine_Part{
      public:
             MyEnginePart(char *name, A_Character *player1, A_Character *player2) 
             : Engine_Part(name){
                  cout << "Creating Engine part: " << name << endl;
                  
                  addObject(*player1);
                  addObject(*player2);            
             };
             
             void run(){
                  (*this)[0].printParameters();
                  (*this)[1].printParameters();
             }
};

int main(int argc, char *argv[]){
    A_Character *player1 = new A_Character ("Bound");
    A_Character *player2 = new A_Character ("Adephi");
    
    MyEnginePart *mep = new MyEnginePart ("First", player1, player2);
    
    Selector *sl = new Selector("Main Menu", mep, 1);
    
    sl->run();
    
    cin.get();
    return 0;
}
#pragma once

class String_Manip
{
  
  public:
        
         bool compare(char* arg1, char* arg2){
              int length1 = 0, length2 = 0, compCount = 0;
              
              for(int i = 0; arg1[i] != '\0'; i++)
                      length1++;
                      
              for(int i = 0; arg2[i] != '\0'; i++)
                      length2++;
                      
              if(length1 != length2)
                         return false;
              else{
                  for(int i = 0; i < length1; i++){
                          if(arg1[i] == arg2[i])
                              compCount++;
                  }
                  return compCount == length1;
              }
         };
      
} s_manip;
This article has been dead for over six months. Start a new discussion instead.