Chapter 12 class and dynamic memory distribution

12.1 dynamic memory and classes

#ifndef D1_STRINGBAD_H
#define D1_STRINGBAD_H

#include <iostream>

class stringbad {
private:
    char * str;
    int len;
    static int num_strings;  //Static member variable. Only one static copy is created
public:
    stringbad(const char *s );
    stringbad();
    ~stringbad();
    friend std::ostream &operator<<(std::ostream &os, const stringbad &st);
};

#endif //D1_STRINGBAD_H
#include "stringbad.h"
#include <cstring>
using std::cout;

int stringbad::num_strings = 0;   //Initialize static variable members, initialize separately

stringbad::stringbad(const char *s) //Constructor
{
    len = std::strlen(s);
    str = new char[len + 1];
    std::strcpy(str,s);
    num_strings++;
    cout << num_strings << ": \"" << str << "\" object created\n";
}

stringbad::stringbad()   //Default constructor 
{
    len = 3;
    str = new char[4];
    std::strcpy(str,"C++");
    num_strings++;
    cout << num_strings << ": \"" << str << "\" default object created\n";
}

stringbad::~stringbad()   //Destructor
{
    cout << "\"" << str << "\" object deleted, ";
    num_strings--;
    cout << num_strings << " left\n";
    delete[] str;

}

std::ostream &operator<<(std::ostream &os, const stringbad &st) {
    os << st.str;
    return os;
}

Static variables and classes:

  • Set static member num_ When the value of strings is initialized to zero, note that static variables cannot be initialized in the class declaration because the declaration describes how to allocate memory, but does not allocate memory. Static member variables can be initialized with separate statements outside the class declaration, because static class members are stored separately, not part of the object.
  • Initialization is carried out in the method file, not in the class declaration file. This is because the class declaration is located in the header file. If the header file is contained by multiple files, the variable will be initialized many times, causing an error.
  • const variable can initialize static data member in class declaration: st
  • atic const int  num_strings = 12;

Constructors and destructors:

If the class member is a pointer, the constructor should allocate enough memory to store it (using new dynamic allocation), and then copy the content to memory;

stringbad::stringbad(const char *s) {
    len = std::strlen(s);
    str = new char[len + 1];  //string is a pointer
    std::strcpy(str,s);
    num_strings++;
    cout << num_strings << ": \"" << str << "\" object created\n";
}

Allocate memory with new in the constructor and delete in the destructor;

  1. When the object expires, the pointer str will also expire, but the memory allocated by new will not be released unless you use delete to release. If you use new [], use delete [] STR when releasing;

Special member functions:

  • Default constructor: the constructor will be called when creating an object. As follows, define a class Klunk. When creating an object:

       Klunk  lunk();

No parameters are passed in at this time, so the default constructor is called:

      Klunk::Klunk()

      {}; / / default values can be defined

  • Copy constructor: used to copy the object into the newly created object, that is, used in the initialization process

       1. Function prototype: class name (const class name &);

       2. When to call the copy constructor:

  1. Explicitly initialize a new object as an existing object:

          stringbad ditto(motto);

          stringbad  metoo = motto;

          stringbad also = stringbad(motto) ;

          stringbad *pstingbad = new stringbad(motto);

     2. When a function passes by value or a function returns an object: (passing by value means creating a copy)

         void callme2(stringbad sb)

         {...};

        3. The function of the default copy constructor: copy the values of static members one by one, which is called shallow copy

        stringbad sailor = sports;

Namely:

       stringbad sailor;

       sailor.str = sports.str; 

       sailor.len = sports.len;

//Instead of copying a string, you copy a pointer to the string to get two pointers to the same string. When one pointer releases memory, the content pointed to by the other is also changed, so an error will occur.

You can change to deep copy:

stringbad::stringbad(const stringbad & st)

{

    num_strings++;

    len = str.len;

    str  = new char [len+1];

    std::strcpy(str,st,str);

}

  • Assignment operator:

stringbad knot;

knot = headline1; / / this is assignment, not initialization;

stringbad knot = heandline1; / / this is initialization, and the assignment operator is not necessarily used;

There will also be the problem of shallow copy mentioned above. You can write the assignment operator:

Prototype: class name & Class Name:: operator=(const class name &);

stringbad & stringbad::operator=(const stringbad & st)

{

        if (this = &st)

                return *this;

        delete [ ] str;

        len = str.len;

        str = new char [len+1];

        std::strcpy(str,st.str);

        return *this;

}

Keywords: C++

Added by 0p3n_p0rT on Tue, 25 Jan 2022 12:51:06 +0200