Search code examples
c++oopdynamic-memory-allocation

Problem with dynamic-memory-allocation while using constructors to a class


i am learning the concept of object oriented programing

Started with dynamic memory allocation , and find a problem in this code . I cant find the problem in this code , in my opinion it all good

#include <iostream>

using namespace std;
class Team
{
    private:
    char *name;
    char stadium[20];
    char city[20];
    public:
    Team(const char *i=" ",const char *stadium=" ",const char *city=" ")
    {
        name=new char [strlen(i)];
        strcpy(name,i);
        strcpy(this->stadium,stadium);
        strcpy(this->city,city);
    }
  const char *getName() {
  return name;
  }
  const char *getCity() {
  return city;
  }
  const char *getStadium() {
  return stadium;
  }
  void setName(char *name) {
  strcpy(this->name, name);
  }
  ~Team() {
      delite [] name;
  }
};

};
int main()
{
  Team *e1 = new Team("Real Madrid", "Madrid", "Santiago Bernabeu");
  Team *e2 = new Team(*e1);
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  e1->setName("Barselona");
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  delete e1;
  delete e2;
   
   return 0;
}

I was looking to fix this problem more then 3 hours ... and didn't find anything , i know this may not be the way i need to search for solution . But i get tired of trying to fix this .

Some of the errors i get

main.cpp: In constructor ‘Team::Team(const char*, const char*, const char*)’:
main.cpp:13:24: error: ‘strlen’ was not declared in this scope
         name=new char [strlen(*i)];
                        ^~~~~~
main.cpp:13:24: note: suggested alternative: ‘mbrlen’
         name=new char [strlen(*i)];
                        ^~~~~~
                        mbrlen
main.cpp:14:9: error: ‘strcpy’ was not declared in this scope
         strcpy(name,i);
         ^~~~~~
main.cpp:14:9: note: suggested alternative: ‘strtoq’
         strcpy(name,i);
         ^~~~~~
         strtoq

I tried this code

#include<iostream>
#include<cstring>
using namespace std;
class Team {
private:
  char *name;
  char city[20];
  char stadion[30];
public:
  Team(char *name = "", char *city = "", char *stadion = "") {
  this->name = new char[20];
  strcpy(this->name, name);
  strcpy(this->city, city);
  strcpy(this->stadion, stadion);
  }
  Team(const Team &e) {
  strcpy(name, e.name);
  strcpy(city, e.city);
  strcpy(stadion, e.stadion);
  }
  const char *getName() {
  return name;
  }
  const char *getCity() {
  return city;
  }
  const char *getStadion() {
  return stadion;
  }
  void setName(char *name) {
  strcpy(this->name, name);
  }
  ~Team() {
     // delite [] name;
  }
};
int main() {
  Team *e1 = new Team("Real Madrid", "Madrid", "Santiago Bernabeu");
  Team *e2 = new Team(*e1);
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  e1->setName("Barselona");
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  delete e1;
  delete e2;
  return 0;
}

And get this error

main.cpp:44:26: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]                                                   
Segmentation fault (core dumped)

Solution

  • I corrected some typos in your code, modified copy constructor of class Team, and it works fine on my PC.

    class Team
    {
    private:
        char* name;
        char stadium[20];
        char city[20];
    public:
        Team(const char* i = " ", const char* stadium = " ", const char* city = " ")
        {
            name = new char[strlen(i) + 1];  // +1 for null-terminate
            strcpy(name, i);
            strcpy(this->stadium, stadium);
            strcpy(this->city, city);
        }
        // allocating memory for Team::name needed, but I delegated it to above constructor.
        Team(const Team& e) :Team(e.name, e.stadium, e.city) {
            // empty
        }
        const char* getName() {
            return name;
        }
        const char* getCity() {
            return city;
        }
        const char* getStadium() {
            return stadium;
        }
        void setName(const char* name) {  // must be const char*. Not char*!!
            strcpy(this->name, name);
        }
        ~Team() noexcept {
            if(name)        
                delete[] name;   // delete[] name, NOT delite
        }
    };
    

    Here is more preferred way of writing C++ classes. As some comments already told, prefer using std::string to char*. I know it maybe hard to get used to a C++ classes but, trust me, std::string is far better than char*. With std::string, you don't need to allocate memory yourself, and you're not required to write additional copy constructor and destructor.

    #include <string>
    
    using std::string;
    
    class Team
    {
    public:
        Team(void) = default;
        explicit Team(const string& name, const string& stadium, const string& city)
            :name_(name), stadium_(stadium), city_(city) {}
    
        void setName(const string& new_name) { name_ = new_name; }
        string getName(void) const { return name_; }
        string getCity(void) const { return city_; }
        string getStadium(void) const { return stadium_; }
    private:
        string name_;
        string stadium_;
        string city_;
    };