C ++ learning notes 8-operators & pointers, learning notes 8-Operators
1. Overload Operators
The return type of the value assignment operator should be the same as that returned by the built-in type assignment operation. The built-in value assignment operation returns a reference to the right operand. Therefore, the value assignment operator also returns a reference to the same class type. For example, the value assignment operator of Sales_item can be declared:
class Sales_item { public: // other members asbefore // equivalent to thesynthesized assignment operator Sales_item&operator=(const Sales_item &); };
2. Merge assignment operators
The synthesis assignment operator is similar to the synthesis copy constructor operation. Assign values to members one by one: each Member of the right operand object is assigned to the corresponding member of the left operand object.
In addition to arrays, each member is assigned a value in the general method of its type. Assign values to each array element to an array.
3. When to call the destructor
The dynamically allocated object is revoked only when the pointer to the object is deleted. If the pointer to a dynamic object is not deleted, the destructor of the object will not be run, and the object will always exist, resulting in Memory leakage, any resources used inside the object will not be released. When the reference or pointer of an object exceeds the scope, the Destructor is not executed. Only when the pointer to the dynamically assigned object is deleted or the actual object (instead of the Object Reference) is out of scope will the Destructor be run. The Destructor is automatically called when the class object is revoked:
// P points todefault constructed object Sales_item * p = newSales_item; {// new scope Sales_item item (* p); // copy constructor copies * p into item delete p; // destructor called on object pointed to by p} // exit localscope; destructor called on item // cancel a container (whether it is a standard library container or a built-in array, the destructor of the class type element in the container will also be run: {Sales_item * p = newSales_item [10]; // dynamically allocated vector <Sales_item> vec (p, p + 10 ); // local object //... delete [] p; // arrayis freed; destructor run on each element}
4. When to compile an explicit destructor
Many classes do not need explicit destructor. In particular, classes with constructors do not need to define their own destructor. The Destructor is required only when some work requires the completion of the destructor.
DestructorIt is often used to release resources obtained by constructors or objects during their lifetime.
If a class requires destructor, it also requires the value assignment operator and the copy constructor. This is a useful empirical rule. This rule is often referred to as the three rule. It refers to all three replication control members if the Destructor is required.
5. How to compile the destructor
Add a font size (~) before the class name (~), It has no return value and no form parameter. An important difference between a destructor and a copy constructor or a value assignment operator is that,
Even if we write our own destructor, the synthesis destructor still runs. For example, you can write the following empty destructor for the Sales_item: class:
class Sales_item { public: // empty; no work todo other than destroying the members, // which happensautomatically ~Sales_item() { } // other members asbefore };
When you cancel an object of the Sales_item type, you will run the Destructor that does nothing. After the Destructor is executed, you will run the synthesis destructor to cancel the members of the class.
The synthesis destructor calls the string destructor to cancel the string member. The string destructor releases the memory that saves the isbn.
Units_sold and revenue Members are of the built-in type, so you do not need to do anything to cancel them by merging destructor.
6. Manage pointers
In class implementation. For classes that contain pointers, pay special attention to replication control because only the addresses in the pointers are copied instead of the objects pointed to by the pointers.
Pointer Error:
When designing a class with pointer members, the class designer must first decide what behavior the pointer should provide. When copying a pointer to another pointer, the two pointers point to the same object. When two pointers direct to the same object, any pointer may be used to change the base object. Similarly, when a pointer deletes an object, the user of the other pointer still thinks that the basic object still exists.
By default, pointer members have the same behavior as pointer objects. However, different replication control policies can implement different behaviors for pointer members. Most C ++ classes use one of the following three methods to manage pointer members:
1. pointer members adopt regular pointer behavior. Such classes have all pointer defects, but do not require special replication control.
2. The class can implement the so-called "smart pointer" behavior. The Pointer Points to an object that is shared, but the class can prevent the suspension pointer.
3. The class adopts a value-type behavior. The objects pointed to by pointers are unique and managed independently by each class object.
7. How to manage pointers
A. Define smart pointers
A. Introduce the usage count
Each time a new object of the class is created, the pointer is initialized and the count is set to 1. When an object is created as a copy of another object, copy the constructor to copy the pointer and add the corresponding Count value. When an object is assigned a value, the value assignment operator reduces the Count value of the object indicated by the left operand (if the count is reduced to 0, the object is deleted ), add the Count value of the object indicated by the right operand. Finally, when calling the destructor, The Destructor reduces the Count value. If the count is reduced to 0, the basic object is deleted.
// private class for use by HasPtr only class U_Ptr { friend class HasPtr; int *ip; size_t use; 625 U_Ptr(int *p): ip(p),use(1) { } ~U_Ptr() { delete ip;} }; /* smart pointerclass: takes ownership of the dynamically allocated * object to which it isbound * User code must dynamically allocate an object to initialize a HasPtr * and must not deletethat object; the HasPtr class will delete it */ class HasPtr { public: // HasPtr owns the pointer; p must have been dynamically allocated HasPtr(int *p, inti): ptr(new U_Ptr(p)), val(i) { } // copy members andincrement the use count HasPtr(const HasPtr&orig): ptr(orig.ptr),val(orig.val) { ++ptr->use; } HasPtr&operator=(const HasPtr&); // if use count goesto zero, delete the U_Ptr object ~HasPtr() { if(--ptr->use == 0) delete ptr; } private: U_Ptr *ptr; // pointsto use-counted U_Ptr class int val; };
B. the assignment and use of the count. assignment operator are a little more complex than the copy constructor:
HasPtr&HasPtr::operator=(const HasPtr &rhs) { ++rhs.ptr->use; //increment use count on rhs first if (--ptr->use ==0) delete ptr; // if usecount goes to 0 on this object,delete it ptr = rhs.ptr; //copy the U_Ptr object val = rhs.val; //copy the int member return *this; }
C. Change other members. Now you need to change the other members accessing int * to indirectly obtain the int through the U_Ptr pointer:
class HasPtr { public: // copy control andconstructors as before // accessors mustchange to fetch value from U_Ptr object int *get_ptr() const{ return ptr->ip; } int get_int() const {return val; } // change theappropriate data member void set_ptr(int *p){ ptr->ip = p; } void set_int(int i) {val = i; } // return or changethe value pointed to, so ok for const objects // Note: *ptr->ipis equivalent to *(ptr->ip) 628 int get_ptr_val()const { return *ptr->ip; } void set_ptr_val(inti) { *ptr->ip = i; } private: U_Ptr *ptr; // pointsto use-counted U_Ptr class int val; };
B. Define Value Type
Another completely different method for processing pointer members is to provide value semantics for pointer members. Objects defined by classes with value semantics act like arithmetic objects. When copying a value object, a new copy is generated. Changes made to the copy are not reflected in the original object, and vice versa. The string class is an example of a value type class.
To make the pointer member behave like a value, you must copy the object pointed to by the pointer when copying the HasPtr object:
/* * Valuelike behavioreven though HasPtr has a pointer member: * Each time we copy aHasPtr object, we make a new copy of the * underlying intobject to which ptr points. */ class HasPtr { public: // no point topassing a pointer if we're going to copy it anyway // store pointer to acopy of the object we're given 630 HasPtr(const int&p, int i): ptr(new int(p)), val(i) {} // copy members andincrement the use count HasPtr(const HasPtr&orig): ptr(new int(*orig.ptr)), val(orig.val) { } HasPtr&operator=(const HasPtr&); ~HasPtr() { deleteptr; } // accessors mustchange to fetch value from Ptr object int get_ptr_val()const { return *ptr; } int get_int() const {return val; } // change theappropriate data member void set_ptr(int *p){ ptr = p; } void set_int(int i) {val = i; } // return or changethe value pointed to, so ok for const objects int *get_ptr() const{ return ptr; } void set_ptr_val(intp) const { *ptr = p; } private: int *ptr; // pointsto an int int val; };
The copy constructor no longer copies pointers. It will allocate a new int object and initialize the object to save the same value as the Copied object. Each object stores different copies of its own int value. Because each object saves its own copy, the Destructor will unconditionally Delete the pointer. The value assignment operator does not need to assign a new object, but must remember to assign a new value to the object to which the Pointer Points, rather than assigning a value to the pointer itself:
HasPtr&HasPtr::operator=(const HasPtr &rhs) { // Note: Every HasPtris guaranteed to point at an actual int; // We know that ptrcannot be a zero pointer *ptr = *rhs.ptr; //copy the value pointed to val = rhs.val; //copy the int return *this; }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
In other words, the Pointer Points to the value instead of the pointer.
8. Summary
In addition to defining operations on this type of object, you also need to define copying, assigning values, or revoking the meaning of this type of object. Special member functions (copy constructor, value assignment operator, and destructor) can be used to define these operations. These operations are collectively referred to as "replication control" functions.
If the class does not define one or more of these operations, the compiler will automatically define them. The merging operation initializes, assigns values, or revokes members one by one. The merging operation obtains each member in sequence and copies, assigns values, or revokes members based on the member type. If the member is of the class type, the merging operation calls the corresponding operation of the class (that is, the copying constructor of the member called by the copy constructor, The destructor of the member called by the destructor, and so on ). If the member is a built-in type or pointer, copy or assign a value directly. The Destructor has no effect on revoking the member of the built-in type or pointer type. If the member is an array, the elements in the array are copied, assigned, or removed as appropriate based on the element type.
Unlike the copy constructor and the assign value operator, a composite destructor is created and run regardless of whether the class defines its own destructor.
If the class defines the destructorRun the synthesis destructor after the bundle.
The most difficult part of defining replication control functions is to recognize their necessity.
Classes that allocate memory or other resources almost always need to define replication control members to manage allocated resources. If a class requires destructor, it almost always needs to define the copy constructor and the value assignment operator.
What is the C language operator?
You can understand operators as built-in and basic functions. They cannot be completely replaced by several functions that do not use the same type of operators. For example, if you use an addition operator, you cannot write a function without + or-to implement addition in any situation.
There is also an important difference between operators and functions. The function itself has a piece of code. When executing a program and encountering a function, it first puts the function parameters into the stack and then jumps to the function code for running. The operator is a local direct operation.
For example
# Include <stdio. h>
# Include <string. h>
Int add (int a, int B)
{Return a + B;
}
Void main ()
{
Int a, B;
B = a + 1;
B = add (a, 1 );
}
After compilation, check the Assembly Code as follows:
11: B = a + 1;
0040D458 mov eax, dword ptr [ebp-4] // get the value of
0040D45B add eax, 1 // add 1
0040D45E mov dword ptr [ebp-8], eax // and assigned to B
12: B = add (a, 1 );
0040D461 push 1 // parameter 1 into Stack
0040D463 mov ecx, dword ptr [ebp-4] // move parameter a to register
0040D466 push ecx // parameter a into the stack
0040D467 call @ ILT + 0 (add) (00401005) // call the function add
0040D46C add esp, 8 // release the memory occupied by the Parameter
0040D46F mov dword ptr [ebp-8], eax // The result is assigned to B
It is obvious that the function calling process is more complex than the operator.
Question about the comma operator in C language?
Many C ++ newbie will ask this question. Everyone knows +-*/and % of others! & | Or something like that, but the comma operator? Maybe half of them will not know what it is.
In fact, we often use the comma operator, but not all the commas in the Code are comma operators.
Let's start with the sample code of a class.
1:
2: class mynum
3 :{
4: public:
5: mynum (double ndb ,...)
6 :{
7: // init with arguments
8 :}
9 :};
10: class someclass
11 :{
12: someclass ():
13: num (3, 4)
14:, a (0)
15:, B (0)
16:, c (15)
17 :{
18: int I, j;
19: I = 1, 2; // int x = 1, 2;
20: for (; B <10; ++ B, -- c)
21 :{
22: ++;
23 :}
24 :}
25: mynum num;
26: int;
27: int B, c;
28 :};
In this Code, the comma appears in lines 5, 13-16, 18-20, and 27.
Now let's take a look at what the comma Operator means.
Then let's look at the above Code
The second row is a comma in the constructor of the mynum class. It is only used to separate the first double type parameter from the variable parameter. This is a special case. If 3.4 is used as the first parameter when constructing a mynum object, and the decimal point is accidentally changed to a comma, 3.4 is changed to two parameters 3 and 4 -- for example, in the case of 13th rows. In this case, the compiler will not report errors and the program can run as well. However, the member variables in the mynum class may be completely different because of the variable values passed in by the constructor. Neither of the two commas is a comma operator.
The comma in lines 14th, 15, and 16 is not a comma operator. The three commas are only used to separate the initialization list of member variables of the constructor.
The int I, j; of the 18th line is a statement commonly used for variable declaration. Here, the comma serves only as an interval variable declaration, not a comma operator.
If you do not know the comma operator, you must think it is wrong! In fact, this is the comma operator. Let's see, after I =; what is the value of I? According to the definition of the comma operator, we can easily obtain I = 2. However, this answer is wrong! When you get the wrong answer, you ignore an important factor-operator priority! Because = has a higher priority, I = 1, 2; this statement is equivalent to (I = 1), 2; if you want to get the expected 2, we should write I = (1, 2 );. The following code can verify this statement (note that 3rd lines are meaningless code, but not error code !)
1: int I, j;
2: I = 1, 2;
3: 3, 4;
4: j = (1, 2 );
5: printf ("% d" n % d "n", I, j );
Continue to read the first line of code, which is a for loop code. The comma here is also a comma operator. In fact, for loop is also a frequent occurrence of comma operators. Only one expression can be written in the for loop, while the comma expression allows you to complete the calculation of two or more expressions. For example, "for (; B <10; ++ B, -- c)", ++ B and -- c will be in each loop... the remaining full text>