new and delete in C++ construct and destructor dynamic_cast analysis

  • 2020-06-19 11:06:00
  • OfStack

1. Differences between new keywords and malloc functions (themselves, functions, applications) :

1. The new keyword is part 1 of C++ :

1, if it is C++ compiler, then you can definitely use new to apply for heap space memory;

2. malloc is a function provided by the C library:

1. malloc cannot be used if there is no corresponding library;

2. In some special embedded development, without C library, dynamic memory allocation cannot be achieved;

3. new performs memory allocation in units of specific types;

1. new is generally used in object orientation instead of malloc;

4. malloc performs memory allocation in bytes;

5. new can be initialized when applying for memory space;

1, trigger the constructor call;

6. malloc only applies for quantitative memory space according to needs;

1. Only new can be used for object creation. malloc is not suitable for object-oriented development.

2. What does the following code output? Why is that? See the differences between new and malloc programming experiments:


#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Test
{
  int* mp; // To illustrate the  free()  Member variables that can cause memory leaks; 
public:
  Test()
  {
    cout << "Test::Test()" << endl;
    mp = new int(100); //  To apply for  4  Two byte heap space and initialized  100 ; 
    cout << *mp << endl;
  }
  ~Test()
  {
    delete mp; //  Destructors return heap space; But if you just use it  free()  The function returns the heap space, where the destructor is not called, the object is not destroyed, and the heap space leaks, which is inexcusable in large projects. 
    cout << "~Test::Test()" << endl;
  }
};
int main()
{
  Test* pn = new Test; //  The first 1 Step to apply heap space, no 2 Step (after successful application) calls the constructor on the heap space, because initialization is required; 
  Test* pm = (Test*)malloc(sizeof(Test)); //  When I'm done with this line of code, pm  It doesn't point to a legitimate object, it just points 1 Slice memory space, this time this piece of memory space can not be 1 Slice legitimate objects, because there are no objects; 
  delete pn; //  Dynamic return of heap space; The first 1 step  delete  Triggers the destructor call, destroys the object, number 2 Step return heap space; In the return of heap space, to destroy the object, otherwise easy to leak memory; 
  free(pm); //  Dynamic programming heap space; Only heap space is returned without triggering destructor calls. It doesn't work here  delete pm , because this would call the constructor on an invalid object, but not on a destructor  delete mp  For, such influence is far-reaching, do not know when will bring  bug , and can not be debugged, only through the way of "code walk" to check whether the two types of application free heap space function; 
  return 0;
}

1. Conclusion:

1. free() can free the heap space applied by new, but free() will not call destructor, so it may cause memory leak.

2. new and delete, malloc and free can only be used together and cannot be mixed.

3. Differences between new and malloc (self, function, application) :

1, new is supported in all C++ compilers;

2. malloc cannot be called in some system development;

3. new can trigger the constructor call;

4. malloc allocates only the required memory space;

5, the object can only be created using new;

6, malloc is not suitable for object-oriented development;

4. What does the following code output? Why is that?

1. Code examples:


int main()
{
  Test* pn = new Test; //  Call the constructor; 
  test* pm = (Test*)malloc(sizeof(Test)); //  Apply for heap space only; 
  delete pn; //  Call the destructor; 
  free(pm); //  Only heap space is freed; 
   return 0;
}

5. Differences between delete and free (self, function, application) :

1, delete is supported in all C++ compilers;

2. free cannot be called in some system development;

3. delete can trigger the call of destructor;

4. free only returns the memory space previously allocated;

5, object destruction can only use delete;

6. free is not suitable for object-oriented development.

6. Can constructors become virtual functions? Can destructors become virtual functions?

7. The constructor cannot be a virtual function:

1, after the constructor execution, the vTABLE pointer will be properly initialized;

1. The polymorphism in C++ is completed by the virtual function table (VF) and pointer to vF table (VF). Vf table pointer is created by the compiler and initialized by the compiler.

2, in the process of structure function performs, virtual function table pointer may not be properly initialized, because for the realization of the virtual function table and virtual function table pointer, for different C + + compiler implementation may not 1 sample, but all the C + + compiler will ensure at the end of the constructor execution, virtual function table pointer is sure to be the correct initialization, before that, there is no guarantee;

3. Therefore, the constructor cannot be a virtual function. When creating an object, we need the constructor to initialize the pointer to the table of virtual functions.

8. Destructor can be a virtual function:

1. Destructor is called before object destruction, which means that the virtual function pointer points to the corresponding virtual function table correctly;

2. It is suggested to declare destructor as virtual function when designing the class (the destructor of a parent class designed in the project is virtual function);

1, assignment compatibility when applying for a subclass object to a parent class pointer, when delete role on the pointer, the compiler will directly depending on the type of the pointer (at this point is the parent class) to invoke the corresponding destructor, if the parent plus virtual, the compiler can according to the pointer to the actual object (subclass) at this time to decide how to call the destructor (polymorphism);

9. Construction, destruction and virtual function programming experiments:


#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
  Base() //  If the request is a destructor, the compiler displays here: error:constructors cannot be declared virtual.
  {
    cout << "Base()" << endl;
  }
  virtual void func() 
  {
    cout << "Base::func()" << endl;
  }
  virtual ~Base() //  The compiler does not display when applying for a virtual function 
  {  
    cout << "~Base()" << endl;
  }
};
class Derived : public Base
{
public:
  Derived()
  {
    cout << "Derived()" << endl;
  }
  virtual void func()
  {
    cout << "Derived::func()" << endl;
  }
  ~Derived()
  { 
    cout << "~Derived()" << endl;
  }
};
int main()
{
  Base* p = new Derived();
  // ...
  delete p; //  Expect to call the subclass destructor and then call the superclass destructor; However, only the parent destructor is called if the parent class is not claimed as a destructor. That's because what you're deleting is 1 A pointer to a parent class, since the destructor is not claimed as  virtual , so in this case, the compiler follows the pointer directly  p  Which type to call 1 A constructor due to a pointer  p  Is the type of the parent class, so the compiler simply assumes that a call to the parent constructor is sufficient. When the virtual function of the parent class is declared as  virtual  , the compiler will not simply follow the pointer  p  To simply call the destructor of a parent or a child class. Since the destructor is a virtual function, the compiler will execute this line of code based on the pointer  p  To determine how to call the destructor, which is polymorphism; 
  return 0;
}

1. When we design a class as the parent class in the project, we will declare the destructor as a virtual function. If not, there may be a memory leak, because the subclass destructor may be skipped.

10. Can polymorphism occur in constructors? Can polymorphism occur in destructors?

11. Polymorphic behavior cannot occur in the constructor (call virtual function in the constructor) :

1. When the constructor executes, the vtable pointer is not properly initialized;

12. Polymorphic behavior cannot occur in destructor (call virtual function in destructor) :

1, the virtual function table pointer may have been destroyed during the destructor execution;

13. Polymorphic behavior cannot occur in destructors and constructors (when calling virtual functions), only the function version in the current class is called;

1. Experiments of calling virtual functions in constructors and destructors:


#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
  Base()
  {
    cout << "Base()" << endl;
    func();
  }
  virtual void func() 
  {
    cout << "Base::func()" << endl;
  }
  virtual ~Base()
  {
    func();
    cout << "~Base()" << endl;
  }
};
class Derived : public Base
{
public:
  Derived()
  {
    cout << "Derived()" << endl;
    func();
  }
  virtual void func()
  {
    cout << "Derived::func()" << endl;
  }
  ~Derived()
  {
    func();
    cout << "~Derived()" << endl;
  }
};
int main()
{
  Base* p = new Derived(); //  print  Base() . Base::func() . Derived() . Derived::func() .                 
  // ...
  delete p; //  print  Derived::func() . ~Derived() . Base::func() .  ~Base() ; 
  return 0;
}

How to use cast correctly in inheritance?

1, dynamic_cast is the inheritance-related type conversion keyword;

2, dynamic_cast requires the related classes to have virtual functions;

3, between Pointers (references) that have direct or indirect inheritance relations;

1. Pointer:

1. Successful conversion: get the pointer of the target type;

2. Conversion fails: 1 null pointer is obtained;

2. Quote:

1. Successful conversion: get the reference of the target type;

2. Conversion fails: 1 exception operation information is obtained;

4. The compiler will check whether dynamic_cast is used correctly.

1, C++ compiler has received enough attention, is a very important position of the type conversion keyword;

2. Error will be reported if incorrect compiler is used;

5. The result of the type conversion is only available during the run phase;

1, dynamic type conversion, conversion results can only be obtained in the running stage;

15. Programming experiment of dynamic_cast:


#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
  Base()
  {
    cout << "Base::Base()" << endl;
  }
  virtual ~Base() //  Engineering experience; 
  {
    cout << "Base::~Base()" << endl;
  }
};
class Derived : public Base
{
};
int main()
{
/* 
    Base* p = new Derived;
  Derived* pd = p; //  Compiler display: error:invalid conversion from 'Base*' to 'Derived*' ; 
           //  If there is no virtual function, use  dynamic_cast  The compiler displays: error: cannot dynamic_cast 'p' (of type 'class Base*') to type 'Derived*' (source type is not polymorphic (polymorphic) )
           //  It has a virtual function and USES it  dynamic_cast  Also want to determine  pd  Is not null; 
*/
  Base* p = new Base;
  Derived* pd = dynamic_cast<Derived*>(p); //  Illegal, cannot use the subclass pointer, pointing to the superclass object; Compiler does not report compiler errors; But at runtime  pd = 0 ;   Means the cast failed here; 
  if( pd != NULL ) //  Such a judgment is necessary; 
  {
    cout << "pd = " << pd << endl;
  }
  else
  {
    cout << "Cast error!" << endl;
  }
  delete p;
  return 0;
}

conclusion


Related articles: