Video 33 - Dynamic Memory Allocation
Static memory
The memory space used to complete its tasks is fixed and can not be dynamically increased or reduced during the running of the program.
Dynamic memory
Dynamic memory consists of nameless, address-only memory blocks that are dynamically allocated during program execution [the main difference from static memory]. They come from a large pool managed by a standard C++ library for you (the term "memory pool"). Requesting some memory from the pool requires a new statement, which allocates a suitable size of memory according to the type of data you provide.
When using dynamic memory, the most important principle is that every new statement must have a delete statement that matches it, otherwise it will lead to memory leaks.
The delete statement only releases the memory block pointed to by the given pointer variable without affecting the pointer. After executing the delete statement, the memory block is released, but the pointer variable still exists. So for general insurance, i = NULL needs to be set
#include <iostream> using namespace std; #include <string> //// Base Class class Company { public: //constructor Company(string theName); //Method virtual void printInfor();//Print information protected: string name; }; //Base Class Constructor Implementation Company::Company(string theName) { name = theName; } //Base Class Method Implementation void Company::printInfor() { cout << "The company's name is:" << name << endl; } //// Subclass class TechCompany:public Company { public: //constructor TechCompany(string theName, string product); //Method void printInfor();//Print information private: string product; }; //Constructor implementation TechCompany::TechCompany(string theName, string product): Company(theName) { this->product = product; } //Method Realization void TechCompany::printInfor() { cout << name << "The company produced it." << product << "\n\n"; } int main() { Company *company = new Company("Apple"); company->printInfor(); delete company;//Delete pointer address company = NULL;//Empty the address pointed to by the pointer company = new TechCompany("APPLE", "IPHONE"); company->printInfor(); delete company;//Delete pointer address return 0; }
Video 34 - Dynamic Array
Although the basic types and objects are allocated memory at runtime with new as mentioned earlier, their sizes are determined at compile time - because the data types we apply for memory for are clearly defined in the program and have a clear unit length; sometimes, they have to wait until the program runs. How much memory should be applied for, and even more memory should be applied according to the operation of the program. For example: int *x = new int[10];//x denotes the array name of an integer array
Delete dynamic arrays
#include <iostream> #include <string> using namespace std; int main() { unsigned int count = 0; cout << "Enter the number of elements in the array:" << '\n'; cin >> count; //The application is made only when the program is running, not when it is compiled, so it is called dynamic. //Apply in the stack, not in the stack. int *x = new int[count]; //Array assignment for(int i = 0; i< count; i++) { x[i] = i; } //Output Printing for(int i = 0; i< count; i++) { cout << "x[" << i << "] = " << x[i] << endl; } return 0; }
PS: (1) Dynamic arrays: applications are made when the program is running, not when it is compiled, so they are called dynamic; applications are made in the heap, not in the stack [general local variables are applied in the stack].
Video 35 - Return memory from functions or methods
Basic idea: Call the new statement in the function to allocate a memory for an object or a basic data type, and return the address of that memory to the main code of the program. The main code will use that memory and release delete immediately after the operation is completed.
#include <iostream> using namespace std; int *newInt(int value) { int *myInt = new int; *myInt = value; return myInt; } int main() { int *x = newInt(20); cout << *x; delete x; x = NULL; return 0; }
#include <iostream> using namespace std; void swap(int *x,int *y) { //Never be executed; if you want to execute, change 0 to 1 #if 0 int temp; temp = *x; *x = *y; *y = temp; #endif //^ XOR operator *x ^= *y; *y ^= *x; *x ^= *y; } int main() { int a,b; a = 3; b = 5; swap(&a,&b); cout << "a = " << a << ", b = " << b << endl; return 0; }
PS:"#if 0........................ # endif statement function and "/*.............................." */” Same.
Function Pointer-Pointer Function
Function pointer: A pointer variable that points to the first address of a function is called a function pointer.
Pointer function: A function can bring back the value of an integer data, the value of a character type and the value of a real type, and the data of a pointer type to point to an address unit.
/**< Function pointer */ #include <stdio.h> int fun(int x,int y) { int z; z = (x > y)? x:y; return z; } int main() { int i,a,b; //Declare function pointers //How a function declares parameters [type, number], then the function pointer should declare parameters, otherwise it will make mistakes. int (*p)(int,int); p = fun;//Assign a function pointer p to function fun printf("Please enter 10 numbers:\n"); scanf("%d", &a); for(i = 0; i< 9; i++) { scanf("%d", &b); a = (*p)(a,b);//Call pointer function fun through pointer p } printf("The Max number is %d.", a); return 0; }
PS: How a parameter variable of a function pointer is declared depends on how the corresponding function parameter variable is declared, including the type and number of parameter variables. eg: In the above program, the function is declared as int fun(int x,int y); then the function pointer is declared as int (*p)(int,int); not int (*p)();
/**< Pointer function */ #include<iostrem> using namespace std; //Declare a pointer function and return an address int *newInt(int value) { int *myInt = new int; *myInt = value; return myInt; } int main() { //Create a new integer variable space and point the x pointer to it int *x = newInt(20); cout << *x; delete x; x = NULL; return 0; }
Video 36 - Copy Constructor
We can assign an object to a variable of the same type, and the compiler will generate the necessary code to assign the values of the attributes of the "source" object to the corresponding members of the "target" object. This assignment behavior is called bit-by-bit replication. (But if some member variables are pointers, the result of object member-by-object replication is that you will have two identical instances in which the same name pointer points to the same address.)
/**< Equivalent overloading with pointer variables */ #include <iostream> using namespace std; class MyClass { public: //constructor MyClass(int *p); //Destructor ~MyClass(); //Operator "=" Overload MyClass &operator = (const MyClass &rhs); void print(); private: int *ptr; }; //Constructor implementation MyClass::MyClass(int *p) { ptr = p; } //Destructor implementation MyClass::~MyClass() { delete ptr; } //Operator (=) overloads implementation, rhs is another object MyClass &MyClass::operator=(const MyClass &rhs) {//When obj1 is not equal to obj2, this pointer refers to the object generated by the current class (in this case, the first MyClass) if(this != &rhs) { delete ptr;//Delete the address ptr and release the memory of obj1 ptr = new int;//Create new memory for pointer ptr *ptr = *rhs.ptr;//Dereference, assigning the value of obj2 to obj1 } else { cout << "Assignment number is the same object on both sides, do not deal with it!\n";//When obj1 = obj2 } return *this;//Returns the first MyClass object } void MyClass::print() { cout << *ptr << endl; } int main() { MyClass obj1(new int(1));//Create object obj1 MyClass obj2(new int(2));//Create object obj2 obj1.print();//Storage value of address pointed by pointer in print object obj1 obj2.print();//Storage value of address pointed by pointer in print object obj2 obj2 = obj1;//obj1 is reloaded to obj2 by equal sign obj1.print();//Storage value of address pointed by pointer in print object obj1 obj2.print();//Storage value of address pointed by pointer in print object obj2 return 0; }
/**< Replica constructor */ #include <iostream> using namespace std; class MyClass { public: //Main constructor [no return type is required] MyClass(int *p); //Replica constructor MyClass(const MyClass &rhs); //Destructor ~MyClass(); //Operator (=) overload, object replication, brackets declare that the object calls the replica constructor MyClass &operator = (const MyClass &rhs); void print(); private: int *ptr; }; //Main Constructor Implementation MyClass::MyClass(int *p) { cout << "Enter the main constructor\n"; ptr = p; cout << "Leave the main constructor\n"; } //Implementation of replica constructor MyClass::MyClass(const MyClass &rhs) { cout << "Enter replica constructor\n"; *this = rhs; //Equivalent assignment overload cout << "Leave the copy constructor\n"; } //Destructor implementation MyClass::~MyClass() { cout << "Enter the destructor\n"; delete ptr; cout << "Leave the destructor\n"; } //Operator (=) overloads implementation, rhs is another object MyClass &MyClass::operator=(const MyClass &rhs) { cout << "Enter assignment statement overload\n"; //When obj1 is not equal to obj2, this pointer refers to the object generated by the current class (in this case, the first MyClass) if(this != &rhs) { delete ptr;//Delete the address ptr and release the memory of obj1 ptr = new int;//Create new memory for pointer ptr *ptr = *rhs.ptr;//Dereference, assigning the value of obj2 to obj1 } else//When obj1 and obj2 are the same object { cout << "Assignment number is the same object on both sides, do not deal with it!\n";//When obj1 = obj2 } cout << "Leave the assignment statement overloaded\n"; return *this;//Returns the first MyClass object } void MyClass::print() { cout << *ptr << endl; } int main() { MyClass obj1(new int(1));//Create object obj1 MyClass obj2(new int(2));//Create object obj2 obj2 = obj1;//obj1 is reloaded to obj2 by equal sign obj1.print();//Storage value of address pointed by pointer in print object obj1 obj2.print();//Storage value of address pointed by pointer in print object obj2 cout << "---------------------------------------------\n"; MyClass obj3(new int(3));//Create object obj3 MyClass obj4 = obj3; obj3.print();//Storage value of address pointed by pointer in print object obj3 obj4.print();//Storage value of address pointed by pointer in print object obj4 cout << "---------------------------------------------\n"; MyClass obj5(new int(5));//Create object obj5 obj5 = obj5; obj5.print();//Storage value of address pointed by pointer in print object obj5 cout << "---------------------------------------------\n"; return 0; }
Running result of program