new-delete_Vector

Table of Contents

1.malloc and new

1.malloc function

2.new keyword

3.free function

4.delete keyword

5.Usage of new and delete keywords

When is the destructor called?

2.Vector

What is Vector?

3.Homework


1.malloc and new

We use a malloc function and enter the disassembly to view the code

1.malloc function

2.new keyword

3.free function

4.delete keyword

5.Usage of new and delete keywords

We found that the functions called by malloc and new are the same system function in the end. new calls the library function malloc, and the compiler implements a certain function for us.

If we want to allocate 1024 bytes of space in the heap, then we can achieve it through malloc

So what if we want to allocate a space of type int, char, or struct in the heap?

New can be used here. The new keyword allows the compiler to implement this function for us.

#include<stdio.h>
int main()
{

int* pi=new int;//Allocate a four-byte space
delete pi;

int* pi=new int(5);//Allocate a four-byte space and assign it a value of 5
delete pi;

int* pi=new int[5];//Allocate 4 four-byte spaces
delete[5] pi;

    Base* pi=new Base;//Allocate 1 byte-like space
delete pi;

Base* pi=new Base[3];//Allocate 3 bytes of space
delete[3] pi;

    Base* pi=new Base(1,2);//Allocate space for a class, and the constructor passes parameters 1, 2
    delete pi;

return 0;
}


Determine whether to release space through the destructor

#include<stdio.h>
#include<stdlib.h>

class Base
{
int x;
int y;
public:
Base(int x,int y)
{
this->x=x;
this->y=y;
}
~Base()
{
printf("delete Base\\
");//Destructor
}
void Print()
{
printf("%d %d\\
",x,y);
}
};
int main()
{

Base* pi=new Base(1,2);
pi->Print();
delete pi;

return 0;
}

When is the destructor called

The destructor is automatically called when the object dies to release the space occupied by the object.

There are four ways to call the destructor:

  • 1. Life cycle: When the object life cycle ends, the destructor will be called.

  • 2.delete: Calling delete will delete the pointer class object.

  • 3. Inclusion relationship: The object Dog is a member of the object Person. When the destructor of Person is called, the destructor of the object Dog is also called.

  • 4. Inheritance relationship: When Person is the parent class of Student, calling the Student’s destructor will call the Person’s destructor.

2.Vector

What is Vector?

Personally, I think vector is actually more like a “remote control”. It has many functions. We can “press the buttons” according to our own needs.

  1. A vector is a sequence container that represents a variable-sized array.
  2. Just like arrays, vectors also use continuous storage space to store elements. This means that you can use subscripts to access the elements of the vector, which is as efficient as an array. But unlike an array, its size can be changed dynamically, and its size will be automatically handled by the container.
  3. Essentially, vector uses a dynamically allocated array to store its elements. When new elements are inserted, the array needs to be resized to increase storage space. This is done by allocating a new array and then moving all elements into this array. In terms of time, this is a relatively expensive task, because the vector is not resized every time a new element is added to the container.
  4. Vector allocation space strategy: vector allocates some extra space to accommodate possible growth because the storage space is larger than the actual storage space required. Different libraries use different strategies to trade off space usage and reallocation. But in any case, the reallocation should be logarithmically increasing in interval size, so that inserting an element at the end is done in constant time.
  5. Therefore, vector takes up more storage space in order to gain the ability to manage storage space and grow dynamically in an efficient manner.
  6. Compared with other dynamic sequence containers (deques, lists and forward_lists), vector is more efficient when accessing elements, and adding and deleting elements at the end is relatively efficient. For other deletion and insertion operations that are not at the end, the efficiency is even lower. Better than unified iterators and references for lists and forward_lists.

3. Homework

Write a Vector to implement functions such as adding, deleting, checking, and modifying

#include<stdio.h>
#include<Windows.h>


#define m_SUCCESS 1 // Success
#define m_ERROR -1 // Failure
#define m_MALLOC_ERROR -2 // Failed to apply for memory
#define m_INDEX_ERROR -3 // Wrong index number
\t\t\t\t\t\t\t\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t
template <class T_ELE>
class Vector
{
public:
Vector();
Vector(DWORD dwSize);
~Vector();
public:
DWORD at(DWORD dwIndex,OUT T_ELE* pEle); //Get the element according to the given index
    DWORD push_back(T_ELE Element); //Store the element to the last position of the container
VOID pop_back(); //Delete the last element
DWORD insert(DWORD dwIndex, T_ELE Element); //Add an element to the specified position
DWORD capacity(); //Returns how many elements can be stored without increasing the capacity
VOID clear(); //Clear all elements
BOOL empty(); // Determine whether the Vector is empty. Return true when it is empty.
DWORD erase(DWORD dwIndex); //Delete the specified element
DWORD size(); //Returns the size of the number of Vector elements
private:
BOOL expand();
private:
DWORD m_dwIndex; //Next available index
DWORD m_dwIncrement; //The size of each increment
DWORD m_dwLen; //The length of the current container
DWORD m_dwInitSize; //Default initialization size
T_ELE *m_pVector; //Container pointer
};
\t\t\t\t\t\t\t
template <class T_ELE>
Vector<T_ELE>::Vector() //Constructor without parameters
:m_dwInitSize(4),m_dwIncrement(5)
{
//1. Create T_ELE objects with length m_dwInitSize
m_pVector=new T_ELE[m_dwInitSize];
//2. Initialize the newly created space
memset(m_pVector,0,sizeof(T_ELE)*m_dwInitSize);
//3.Set other values
m_dwIndex=0;
m_dwLen=m_dwInitSize;
}
\t\t\t\t\t\t\t\t\t\t
template <class T_ELE> //Constructor with parameters
Vector<T_ELE>::Vector(DWORD dwSize)
:m_dwIncrement(5)
{
//1. Create T_ELE objects with a length of dwSize
m_pVector=new T_ELE[dwSize];
//2. Initialize the newly created space
memset(m_pVector,0,sizeof(T_ELE)*dwSize);
//3.Set other values
m_dwIndex=0;
m_dwLen=dwSize;

}

template <class T_ELE> //Release space
Vector<T_ELE>::~Vector()
{
\t\t\t\t\t\t\t\t\t\t\t
//Release space delete[]
delete [] m_pVector;
m_pVector=NULL;
\t\t\t\t\t\t\t\t\t\t\t
}
\t\t\t\t\t\t\t\t\t\t\t
template <class T_ELE>
BOOL Vector<T_ELE>::expand() //Expand the capacity
{
// 1. Calculate the increased length
DWORD tmp_Size=m_dwLen + m_dwIncrement;
\t\t
// 2. Apply for space
T_ELE* tmp_pVector = new T_ELE[tmp_Size];
memset(tmp_pVector,0,tmp_Size*sizeof(T_ELE));//Initialize space
// 3. Copy data to new space
memcpy(tmp_pVector,m_pVector,m_dwLen*sizeof(T_ELE));
\t\t\t\t\t\t\t\t\t\t\t
// 4. Release the original space
delete[] m_pVector;
m_pVector=tmp_pVector;
tmp_pVector=NULL;
// 5. Assign values to various attributes
m_dwLen=tmp_Size; //The Index is not modified at this time because the length attribute is modified in other insertion functions.

return m_SUCCESS;
\t\t\t\t\t\t\t\t\t\t\t
}
\t\t\t\t\t\t\t\t\t\t\t
template <class T_ELE>
DWORD Vector<T_ELE>::push_back(T_ELE Element) //Writing function, if one is not saved in the space, the first one will be saved. If it is saved, then the next one will be saved.
{
//1. Determine whether the capacity needs to be increased, and if so, call the capacity increase function.
if(m_dwIndex>=m_dwLen)
{
expand();
}
//2. Copy the new element to the last position of the container
memcpy( & amp;m_pVector[m_dwIndex], & amp;Element,sizeof(T_ELE));
//3. Modify attribute values
m_dwIndex + + ; //The length attribute is not modified at this time because the length attribute has already been modified in the capacity expansion function.
\t
return m_SUCCESS;
}
\t\t\t\t\t\t\t\t\t\t\t
template <class T_ELE>
DWORD Vector<T_ELE>::insert(DWORD dwIndex, T_ELE Element) //Insert function
{
//1. Determine whether the index is within a reasonable range
if(dwIndex>m_dwLen || dwIndex<0)
{
return m_INDEX_ERROR;
}
\t\t\t\t\t\t\t\t\t\t\t\t\t
//2. Determine whether the capacity needs to be increased, and if so, call the capacity increase function.
if(m_dwIndex>=m_dwLen)
{
expand();
}
// 0 1 2 3 4 5 6 7
//3. Move the element after dwIndex back
for(int i=m_dwIndex;i>dwIndex;i--)
{
memcpy( & amp;m_pVector[i], & amp;m_pVector[i-1],sizeof(T_ELE));
}
\t\t\t\t\t\t\t\t\t\t\t
//4. Copy the Element element to the dwIndex position
memcpy( & amp;m_pVector[dwIndex], & amp;Element,sizeof(T_ELE));
\t\t\t\t\t\t\t\t\t\t\t
//5. Modify attribute values
m_dwIndex + + ;

return m_SUCCESS;
}
\t\t\t\t\t\t\t\t\t\t\t
template <class T_ELE>
DWORD Vector<T_ELE>::at(DWORD dwIndex,T_ELE* pEle)
{
//Judge whether the index is within a reasonable range
if(dwIndex>=m_dwIndex)
{
return m_INDEX_ERROR;
}
\t\t\t\t\t\t\t\t\t\t\t
//Copy the value of dwIndex to the memory specified by pEle
memcpy(pEle, & amp;m_pVector[dwIndex],sizeof(T_ELE));

return m_SUCCESS;
}
\t
template <class T_ELE>
VOID Vector<T_ELE>::pop_back() //Realize deletion of the last element
{
//The previous index of m_dwIndex is the index of the last element
T_ELE x=0;
memcpy( & amp;m_pVector[m_dwIndex-1], & amp;x,sizeof(x));

//Modify properties
m_dwIndex-=1;

}

template <class T_ELE>
DWORD Vector<T_ELE>::capacity() //Returns how many elements can be stored without increasing the capacity
{
DWORD x=m_dwLen-m_dwIndex;
return x;
}

template <class T_ELE>
VOID Vector<T_ELE>::clear() //Clear all elements
{
//Initialize all elements
memset( & amp;m_pVector[0],0,sizeof(T_ELE)*m_dwLen);

//Modify properties
m_dwIndex=0;

}

template <class T_ELE>
DWORD Vector<T_ELE>::size() //Returns the number of existing elements
{
//Return the number of existing elements
return m_dwIndex;

}

template <class T_ELE> //Determine whether Vector is empty
BOOL Vector<T_ELE>::empty()
{
if(m_dwIndex==0)
return true;
else
return false;
}

template <class T_ELE>
DWORD Vector<T_ELE>::erase(DWORD dwIndex)
{
//Determine whether the receiving index is illegal
if(dwIndex>=m_dwIndex || dwIndex<0)
return m_INDEX_ERROR;
//Determine whether the number of elements is 0
if(m_dwIndex!=0)
{
//Delete the specified index element
for(int i=dwIndex;i<m_dwIndex;i + + )
{
memcpy( & amp;m_pVector[i], & amp;m_pVector[i + 1],sizeof(T_ELE));
}
//Initialize the last element
memset( & amp;m_pVector[m_dwIndex-1],0,sizeof(T_ELE));
}

//Modify properties
m_dwIndex-=1;
}
\t
//Other functions. . Realize it yourself
voidTest()
{
Vector<int>* pVector=new Vector<int>(4);
pVector->push_back(1);
pVector->push_back(2);
pVector->push_back(3);
pVector->push_back(4);
//pVector->insert(0,9);
    /*
int x=0;
pVector->at(3, & amp;x);
printf("%d\\
",x);
pVector->pop_back();
pVector->at(3, & amp;x);
printf("%d\\
",x);
*/
//printf("%d\\
",pVector->capacity());
//pVector->clear();
//printf("%d\\
",pVector->size());
//printf("%d\\
",pVector->empty());
pVector->erase(0);
}
int main()
{
Test();

return 0;
}