C++ Beginner Learning 01

 The difference between structure and C


  • The struct keyword is no longer needed on the type, just use the structure name directly
  • Functions are allowed in C++ structures:
    • ①Declared in the structure and implemented outside the structure (can also be implemented directly within the structure);
    • ②The data accessed in the structure function can be accessed directly;
    • Call (same as data members):
      • (1) Object (structure variable).Member
      • (2) Object pointer -> member
      • (3) (*Object pointer).Member
  • When C++ does not write constructors and permission restrictions, the usage is the same as C language.

memory pool


 

#include <iostream>

using namespace std;
//允许申请一段内存,供给程序使用,综合管理内存
//malloc 内存是在堆区
//calloc 内存是在自由储存区

void testMemory()
{
    char* memorySum = new char[1024];

    //int* pNum = new(申请内存的开始位置) int[3];
    int* pNum = new(memorySum) int[3]{1,2,3];

    //char* pstr = new(pNum+3) char[20]{"Iloveyou"};//与下面一句等效
    char* pstr = new(memorySum+12) char[20]{"Iloveyou"};   


    for(int i = 0; i < 3; i++)
    {
        cout<<pNum[i]<<" ";

    }
    cout<<endl;
    
/*等效for(int i = 0; i < 3; i++)
 *   {
 *      cout<<((int*)memorySum)[i]<<" ";
 *
 *   }
 */  cout<<endl<<pstr<<endl;
     cout<<(memorySum+12)<<endl;
    
    delete[] memorySum;
    memorySum = nullptr;
}
int main()
{
    testMemory();
    return 0;
}

string type


  • stringcreate
    • ①With initialization
    • ②Without initialization
    • ③ Created through another string
  • Basic string operations: ① copy; ② assignment; ③ connection; ④ comparison.
  • to_string() function
    string str1 = "Iloveyou";
    
    string str2 = to_string(1234);
    
    cout<<str2<<endl; 

function


function Function
capacity() The number of data that the container can store
size() The number of elements currently present in the container
reserve() Specify the number of data that the container can store
resize() Respecify the number of valid elements, differing from reserve() in specifying the size of the capacity.

 classes and objects



//关键字  类名
Class   classname
{
    Access specifiers:           //访问修饰符,有三种public   protected  private

    Data members/variables;       //数据成员/变量

    Member functions(){}          //方法(成员函数)


}
  • The declaration of member functions is in the class, and the definition is generally outside the class;
    • The use of member functions in a class needs to be qualified by the class name, such as Box::get(void), where Box is the class name, "::" is the access symbol, also called the range resolution operator or domain operator, get () is the function declared in the class, void is the parameter;
    • Due to permission restrictions, data members/variables in classes generally cannot be used directly. It is necessary to redefine a set of corresponding data members/variables and call them in functions, such as length = len; breadth = bre; height = hei;
class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
      // 成员函数声明
      double get(void);
      void set( double len, double bre, double hei );
};
// 成员函数定义
double Box::get(void)           //::是域操作符,Box是类名,get()是类中的成员函数,void是参数
{
    return length * breadth * height;
}
 
void Box::set( double len, double bre, double hei)   //重新定义相应的数据成员/对象
{
    length = len;                         
    breadth = bre;
    height = hei;
}
  • Calling a member function uses the dot operator ( . ) on the object so that it can operate on data related to the object;
    Box myBox;          // 创建一个对象
     
    myBox.get();  // 调用该对象的成员函数

 Class constructors and destructors


  • The constructor of a class is a special member function of the class that is executed every time a new object of the class is created. The name of the constructor is exactly the same as the name of the class and does not return any type or void. Function: The constructor can be used to set initial values ​​for some member variables.
    • The default constructor does not have any parameters, but the constructor can also take parameters if needed. In this way, an initial value will be assigned to the object when it is created.
    • There is only one default constructor in any class. When we write the constructor ourselves, the default one does not exist. But you can write more than one constructor and write constructors with different numbers of parameters, such as
      class Ti
      {
      public:
      
          Ti(string _name,int _age){              //第一个构造函数
              name = _name;
              age = _age;
              cout<<"带参构造函数"<<endl;
          }
      
          Ti(){
              cout<<"无参构造函数"<<endl;
          }                                  //第二个构造函数
      
      protected:
      
          string name = "Jone";
          age = 18;
      
      }
      
      int main()
      {
          Ti skt("jone",28);                     
          Ti rng;
      }

    • The constructor has several parameters. When creating the corresponding object in the main function, you also need to write the corresponding number of parameters, such as
      class Ti
      {
      public:
      
          Ti(string _name,int _age){            //见下
              
              name = _name;
              age = _age;
              
          }
      
      protected:
      
          string name = "Jone";
          age = 18;
      
      }
      
      int main()
      {
          Ti ti("jone",28);                     //参数数量需要与类中构造函数定义的参数数量相同
      
      
      }

    • The constructor can be deleted directly using delete and operated in the class, such as Line()=delete;
    • In order to construct functions of different styles, the constructor can be defaulted in the class, so that the use of the constructor in the main function is not limited to a fixed number of parameters (not exceeding the maximum number):
      class girl
      {
      public:
      
          girl(string _name = "",int _age = 18){      //""内的部分省略了,于是主函数中相应的构造函
              name = _name;                           //数不超过两个的,都可以创建,如0,1,2个参数
              age = _age;
          }
          
      protected:
          string name;
          int age;     
      
      };
      
      int main()
      {
          girl girl1;                                   //无参数
          girl girl2("Lisa");                           //一个参数
          girl girl3("Kasa",19);                        //两个参数
      
          return 0;
      }

    • To use the default constructor, you can use default, such as Line()=default;
      class Line
      {
         public:
            void setLength( double len );
            double getLength( void );
            Line() = default;   // 使用默认的构造函数
      
       
         private:
            double length;
      };
    • For the constructor, you can use the initialization list to initialize the fields in the following format: Constructor name (parameter 1, parameter 2,...): member 1 (parameter 1), member 2 (parameter 2),...{}
      class Line
      {
         public:
            void setLength( double len );
            double getLength( void );
            Line();   // 这是构造函数声明
          //Line() = delete;   //删除构造函数
       
         private:
            double length;
      };
      
      Line::Line( double len): length(len)   //使用初始化列表来初始化字段
      {
          cout << "Object is being created, length = " << len << endl;
      }
      
      //等效于下面未使用初始化列表的初始化方式
      
      Line::Line( double len)
      {
          length = len;
          cout << "Object is being created, length = " << len << endl;
      }
       
      • You can use a constructor to call another constructor by initializing the parameter list, also called delegate construction;
        class student
        {
        pubilc:
            GIF(string name,int age):name(_name),age(_age) {}
        
            //通过初始化列表的方式用构造函数调用另一个构造函数,也叫做委托构造
            GIF():GIF("名字",18) {}                  
            
            void print
            {
                cout<<name<<"\t"<<age<<endl;
            }
        
        protected:
            string name;
            int age;
        
        }

  • The destructor of a class is a special member function of a class that is executed every time a created object is deleted. The name of the destructor is exactly the same as the name of the class, except that it is prefixed with a tilde (~). It does not return any value and cannot take any parameters. Destructors help release resources before exiting the program (such as closing files, releasing memory, etc.).
    • When the data members in the class are pointers and apply for dynamic memory, a handwritten destructor is required.
    • Generally, the destructor does not need to be called manually, and the call of the destructor does not mean the end of the life cycle.

copy constructor

  • The copy constructor is also a constructor function and looks the same as the constructor, but the parameters are fixed;
    • The function of the copy constructor is to initialize one object through another object, that is, when creating another new object through an object, the copy constructor needs to be called;
    • Even if you don't write a copy constructor, there is still a default copy constructor // We will talk about shallow copy later;
    • An important basis for distinguishing whether a function is a copy constructor, whether an object is created, and comparing parameters (MM mm) and (MM& mm);

    • Note that the copy constructor is const modified. If not modified, an error may be reported when assigning values ​​to anonymous objects;
    • //对比上面一个代码框的代码(默认的拷贝构造函数),现在这个是手写的拷贝构造函数
      class MM
      {
      public:
          MM(string _name,int _age) :name(_name),age(_age) {}
          void print()
          {
              cout<<name<<"\t"<<age,,endl;
          }
      
          //拷贝构造函数
          MM(const MM& mm)                   //MM girl(mm);   //const作用看下方匿名对象
          {
              name = mm.name;                //girl.name = mm.name;
              age = mm.age;                  //girl.age = mm.age;
              cout<<"拷贝构造"<<endl;
          }
          //右值引用拷贝构造           //当使用右值引用操作后,主函数中创建对象是不可以进行赋值操作
          //MM(MM&& mm)
          //{
          //    name = mm.name;                //girl.name = mm.name;
          //    age = mm.age;                  //girl.age = mm.age;
          //    cout<<"右值引用拷贝构造"<<endl;        
          //}
      
      protected:
          string name;
          int age;
      }
      
      void printData(MM mm)        //MM mm = 实参;创建了一个对象,这一种调用了拷贝构造函数
      {
          mm.print();
      }
      void printData2(MM& mm)      //调用形参,没有创建对象,不存在拷贝本,没有调用拷贝构造函数
      {
          mm.print();
      }
      
      int main()
      {
          MM mm("mm",18);
          mm.print();
      
          //显式调用
          MM girl(mm);                    //现在调用的是上面手写的拷贝构造函数
          girl.print();
      
          //隐式调用
          MM girl2 = mm;
          girl2.print();
      
          //注意:这种不是拷贝构造,而是运算符重载
          MM girl3;
          girl3 = mm;
          girl3.print();   
      
          //无名对象  匿名对象                 
          MM temp;                 
          temp = MM("匿名",18);            //进行右值操作后不能进行赋值操作
          temp.print();
      
          //匿名对象创建对象的时候,一定要用const修饰
          MM temp2 = MM("匿名",19);   //用右值操作可以,上方构造函数创建对象没用const修饰不可以
          temp.print();               
      
      
      }

Dark and shallow copy

  • Shallow copy: The default copy structure is called shallow copy, because destruction problems (repeated memory release problems) will occur.
  • Deep copy: Perform dynamic memory application in the constructor, that is, perform new operation in the constructor and perform copy assignment (strcpy) operation.
//由于浅拷贝会出现析构问题(重复释放内存)而出现错误导致程序崩溃
//如若不进行深拷贝,创建的三个对象里的name指针指向了同一个内存,即最初开辟的"baby"所指向的内存区域

#include<iostream>
#include<string>
#include<cstring>

using namespace std;

class MM
{
public:
    MM(const char* mname, int age) :age(_age)
        {
            name = new char[strlen(mname) + 1];
            strcpy_s(name,strlen(mname) + 1, mname);
        }

    void prnt()
        {
            cout<<name<<"\t"<<age<<endl;
        }
    MM(const MM& object)             //通过赋值的方式,也是浅拷贝,加上动态内存申请就是深拷贝
        {
            name = object.name;
           //深拷贝需要做动态内存申请,也就是重新new,strcpy一遍
            {
                name = new char[strlen(object.name) + 1];             
                strcpy_s(name,strlen(object.name) + 1,object.name);//+1是字符串结束标记
            }   
            age = object.age;
        }
    ~MM()
        {
            delete[] name;
        }

protected:
    char* name;
    int age;
}

int main()
{
    MM mm("baby",19);
    //下面两种都叫浅拷贝,都是通过默认的拷贝构造创建的对象
    MM girl(mm);
    MM gm = mm;

    mm.print();
    girl.print();
    gm.print();

    return 0;
}

Construction order and destruction order issues

  • The construction order and destruction order of ordinary objects are opposite;
  • The object that comes out of new will be destructed directly when deleted;
  • static object, released when the program is closed;
#include<iostream>
#include<string>

using namespace std;

class MM
{
public:
    MM(string name = "x") :name(name)
        {
            cout<<name;
        }
    ~MM()
        {
            cout<<name;
        }

protected:
    string name;
}

int main()
{
    {   //普通变量的构造顺序和析构顺序相反
        MM mm1("A");              //A
        static MM mm2("B");       //B    static定义的变量在程序关闭的时候生命周期才会结束
        MM* p3 = new MM("C");     //C
        MM mm4[4];                //xxxx
        delete p3;                //C    delete 直接调用析构函数
        p3 = nullptr;
                                  //xxxxAB
    }
    //最终结果:ABCxxxxCxxxxAB


    return 0;
}

 

C++ structure constructor

  • Structures and classes have similarities and differences;
#include <iostream>
#include <string>

using namespace std;

struct MM
{
    //默认为公有属性,权限限定词(public/protected/proviate)也是可以用的
    string name;
    int age;
    //MM(string name) :name(name)
    //{
    //    cout<<"构造函数"<<endl;
    //}

};


int main()
{
    //采用创建时候赋值的方式,也是调用构造函数
    
    MM object = {"Lisa",18};      //如果这么写,需要在上面struct中写一个含有两个参数的构造函数
    cout << object.name << "\t" << object.age << endl;


}

Guess you like

Origin blog.csdn.net/qq_59470001/article/details/127403691