128-C++ Study Sixth

class Int
{
    
    
private:
	int value;
public:
	Int(int x=0):value(x){
    
    }
	~Int(){
    
    }
	int &Value(){
    
    return value;}
	const int&Value()const{
    
    return value;}
};

class Object
{
    
    
	int num;
	Int*pInt;
public:
	Object(int x=0):num(x),pInt(new Int(x+10)){
    
    }
	~Object()
	{
    
    
		if(pInt!=nullptr)
		{
    
    
			delete pInt;
		}
		pInt=nullptr;
	}
	int GetNum(){
    
     return num;}

	Int&GetInt(){
    
     return *pInt;}

	Int*GetPInt(){
    
    return pInt;}

};


int main()
{
    
    
	Object Obj(10);

	Int*p=Obj.GetPInt();

	Int x=Obj.GetInt();

	return 0;
}

When our main function is running, a stack frame is opened for the main function, and an Obj object is defined. The members of this object are: num and pInt, num=10, pInt pointer new an Int space (4 bytes) x+10 =20, take 20 to initialize this space. New here has two actions: apply for space and take the constructor of Int to construct an object (initialize 20), and give the address of the constructed object to pInt
Int*p=Obj.GetPInt(); Give the content of pInt to p, p The pointer points to the object 20.
Int x=Obj.GetInt(); returns the object pointed to, and assigns the object copy to x
Insert picture description here

Obj.GetPInt()->Value()=100;

According to the calling relationship of the function, it is transferred from left to right. Obj.GetPInt() calls GetPInt() function to return the pointer PInt of Int type. Value() is the method to point to the object. 100 is the value value, which is actually PInt. Assign value to the pointed object, 20 becomes 100

Question:
If there is no & before GetInt()

Int GetInt(){
    
     return *pInt;}

Can the following three sentences be executed?

Int x=Obj.GetInt();//可以
int a=Obj.GetInt().Value();//可以
Obj.GetInt().Value()=100;//没必要

When we mobilize the GetInt() function, we will open up a stack frame for this function, give it the this pointer, and return the *pInt object. We need to mobilize the copy constructor to use the temporary object as a transition (temporary object). Built in the main function stack area), assign this temporary object to x, so the first line of code is correct. In the second line of code, the previous return is also a dead value, and the value of the dead value is taken out to a. The second line of code is correct. But the third line of code is to change the value of the dead value. After the change is meaningless, this value is quickly destroyed, and the dead value cannot be assigned.

Add & in front of GetInt(), it's OK

Int&GetInt(){
    
     return *pInt;}

What is returned is the object pointed to by pInt itself! 100 changes are the objects pointed to by pInt in Obj

In C++, you can overload * overload ->

Int& operator*() {
    
     return *pInt; }
const Int& operator*() const {
    
     return *pInt; }

Int* operator->() 
	{
    
     
		return pInt;  
		//return &**this; 两种写法都可以 
	}

Int& operator*() {return * pInt; }
Overload*, it returns what pInt refers to
const Int& operator*() const {return *pInt;} This is a regular method, and it returns what pInt refers to. In order to maintain consistency, it has also been returned in the form of const Int&,

int main()
{
    
    
	Object obj(10);
	Int a = *obj;
	int x = (*obj).Value();
	(*obj).Value() = 100;

	return 0;
}

Now it is equivalent to the function giving a new name, overloading to understand the reference to
see the program: an object obj is defined, its num=10, and the pInt pointer points to an Int object. The constructor constructs an Int type object with a value of 20, *obj is equivalent to mobilizing its own operator overload, dereferencing, and directly returning the pointed object to a, (*obj).Value(), giving 20 to x, (*obj).Value() = 100; turning 20 into 100
This overload* is very similar to pointers
Insert picture description here

About overloading ->

Insert picture description here
this points to obj, this is the object itself, * * this mobilization points to overload, and returns the alias of the object pointed to by pInt, & returns the address of this object

int main()
{
    
    
	Object obj(10);
	obj->Value();
	obj.operator->()->Value();
	return 0;
}

obj. is the method of the object itself
obj-> is overloaded ->, the returned object is an object of type Int, return (*Int), -> is first combined with the object itself, and returns the type of the pointed object, also That is (*Int), then (*Int)->Value(); In fact, this place -> works twice. You only need to write a -> to
overload * and ->, this type is called smart pointer

Overload()

Functor

class Add_Int
{
    
    
private:
	int value;
public:
	Add_Int(int x = 0) :value(x) {
    
    }
	~Add_Int() {
    
    }
public:
	//int operator()(Add_Int * const this,int x,int y)
	inline int operator()(int x, int y)
	{
    
    
		value = x + y;
		return value;
	}
};
int main()
{
    
    
	Add_Int add;
	int x = add(10, 20);//重载()
	int y = add.operator()(10, 20);//解析
	//  y = operator()(&add,10,20);		//正确
	//  y = operator(&add)(10,20);		//错误,因为这里的()是函数名
	x = Add_Int(0)(12, 23);//类型名后面加()意味着构建对象,拿对象调动()重载

}

There are only unary and binary functors in the standard library

class Stack
{
    
    
private:
	double data[10000000];//超过内存,崩溃
	int maxsize;
	int pos;
public:
	Stack() {
    
     pos = -1; }
	~Stack() {
    
    }

	int size()const {
    
     return pos + 1; }
	int empty() const {
    
     return size() == 0; }
	int full() const {
    
     return size() == maxsize; }
	void push(double x)
	{
    
    
		pos += 1;
		data[pos] = x;
	}
	// pop
	double Top() {
    
     return data[pos]; }
	void  pop() {
    
     pos -= 1; }
};

int main()	  //主函数栈区大小 vs 1M // Liunx // 10M
{
    
    
	Stack st;//开辟在局部变量区
	return 0;
}

The above method is not good, the type is not convenient to convert, and it is not satisfied with the user

Template type

template<typename Type>//Type是标识符
class Stack
{
    
    
	Type* data;
	int maxsize;
	int pos;
public:
	Stack(int sz = 10)
	{
    
    
		maxsize = sz;
		pos = -1;
		data = new Type[maxsize];  //???
		// 1 // 2;
		//cout << typeid(Type).name() << endl;
		//打印出int, double, student 
		//typeid(Type).name x;//错误 
		//     string
	}
	~Stack()
	{
    
    
		maxsize = 0;
		pos = -1;
		delete[]data;
		data = nullptr;
	}
	int size() const {
    
    
		return pos + 1;
	}
	bool empty() const {
    
    
		return size() == 0;
	}
	bool full() const {
    
    
		return size() == maxsize;
	}
	void push(const Type& x)
	{
    
    
		if (!full())
		{
    
    
			pos += 1;
			data[pos] = x;
		}
	}
	Type& top() {
    
    
		return data[pos];
	}
	const Type& top() const {
    
    
		return data[pos];
	}
	void pop() {
    
    
		pos -= 1;
	}
};

? Why are these next three sections plus const
Insert picture description here
we might define a common stack Stack;
also possible to define recurring stack const Stack;
ordinary objects can mobilize ordinary method, the method can also mobilize the often
often subject only to mobilize the method often
write plus The degree of reuse of this code

from the perspective of the entire type design

Insert picture description here
One is the normal method, the value cannot be changed, the
other is the normal method, the value can be changed

How is this stack method used?

int main()
{
    
    
	Stack<int> ist(100);
	Stack<double> dst;
	Stack<Student> sst;
	///ist = dst;
	return 0;
}

When compiling, the compiler finds that you have defined a template type stack and put the compiled template type stack in the description table. When compiling the main function, it finds the given int and generates a piece of code.
Insert picture description here
Then see double, and generate a piece of code.
Insert picture description here
Then see student, and generate a piece of code. The
Insert picture description here
template class is the type of the generated type.
Insert picture description here
Note that this process is determined at compile time.
Be sure to specify the three pieces of code in <>
Insert picture description here
After compilation, the obj file is formed, and the link is formed into an executable file. The
template is the code that generates the code (compiler)

Only in the template, when this method is called, it participates in compilation. This method is not mobilized, and the compiler cannot check whether there is a problem with this method.

The stack types are different and cannot be assigned to each other. The types do not match. After the compilation is completed, the type name changes. The type is Stack< int> and the type is a different type of Stack< double>

Next to solve this problem
Insert picture description here

class Object
{
    
    
private:
	int value;
public:
	Object(int x = 0) :value(x)
	{
    
    
		cout << "construct object: " << this << endl;
	}
	~Object()
	{
    
    
		cout << "deconstruct object: " << this << endl;
	}
};

int main()
{
    
    
	Stack<Object> ost;
	cout << ost.empty() << endl;
	return 0;
}

Define an empty stack
Insert picture description here
Logically speaking, it is an empty stack, empty is true

int main()
{
    
    
	Stack<Object> ost;
	cout << ost.size() << endl;
	return 0;
}

Insert picture description here

Stack 0, but when building, 10 objects are built, the logical and physical difference

STL

string class


#include<string>
#include<iostream>
using namespace std;
int main()
{
    
    
	string s1("yhpinghello");
	string s2 = "yhping";

	string s3; 

	s3 = s1 + s2;
	s3 = s1 + "yhping";
	s3 = "yhping" + s1;
	s3 = "hello" + "yhping";//错误,这个不可行,常性字符串,没有+
	
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	return 0;
}
int main()
{
    
    
	string s1("yhping");  
	string s2("yhx");

	cout << (s1 < s2) << endl;//比较
	s1.append("hello");//尾部接
	cout << s1 << endl;

	int len = s1.size();//大小
	int cap = s1.capacity();//容量一定大于字符串的个数
	for (int i = 0; i < len; ++i)
	{
    
    
		cout << s1[i] << " ";//下标访问
	}
	//s1[10] = 'x';//改变字符串内容 可以检查越界
	cout << s1 << endl;
	const char* s = s1.c_str();//返回s1字符串的地址
	return 0;
}

vector

Equivalent to expandable array

#include<vector>
#include<iostream>
using namespace std;
int main()
{
    
    
	vector<int> iar = {
    
     12,23,34,45,56,67,78 };//可以直接初始化 
	vector<double> dar;
	//vector<Student> sar;要什么添加什么,vector就操作什么 

	int n = iar.size();//个数 
	for (int i = 0; i < n; ++i)
	{
    
    
		cout << iar[i] << " ";//打印 
	}
	iar.push_back(100);//尾部添加数据,但是没有头部添加的方法 
	
	int a = iar.back();//返回最后一个元素 
	int x = iar.front();//返回第一个元素 

	iar.clear();//清空
	return 0;
}

Iterator

//迭代器,面向对象版本的指针 
int main()
{
    
    
	vector<int> iar = {
    
     12,23,34,56,67,78 };

	vector<int>::iterator it = iar.begin();//内置类型迭代器,it迭代器类型,begin获取顺序元素的第一个元素的位置信息 
	for (; it != iar.end(); ++it)//end代表顺序元素的最后一个元素的后续位置,78后面的后续位置 
	{
    
    
		cout << *it << endl;//迭代器从前向后依次访问 ,*it所指之物 
	}

	return 0;
}

Insert picture description here

Guess you like

Origin blog.csdn.net/LINZEYU666/article/details/112143516