The difference between Pointers and references

  1. Non-null distinction: References to null values cannot be used under any circumstances; a reference must always refer to some object. Pointers can point to null.

  2. Validity difference: References do not need to be tested for validity before being used; Pointers should always be tested to prevent them from being null

  3. Modifiability difference: A reference specifies an object at initialization and cannot be modified later.

Pointers pass dynamic memory

Example 1: What happens when the program is tested?

#include<iostream>
#include<cstring>
using namespace std;

void getMemory(char*p, int num)
{
    p = (char*)malloc(sizeof(char) * num);
}

int main(int argc, const char* argv[])
{
    char *str = NULL;
    getMemory(str, 100);
    strcpy(str, "hello");
    return 0;
}
Copy the code

The problem is in getMemory, where the compiler always makes a temporary copy of each argument to a function. In this case, p is a copy of STR, but it does not affect STR. Strcpy () is still NULL, and the code crashes.

The correct way to do this is to pass the address of STR into getMemory.

#include<iostream>
#include<cstring>
using namespace std;

void getMemory(char**p, int num)
{
    *p = (char*)malloc(sizeof(char) * num);
}

int main(int argc, const char* argv[])
{
    char *str = NULL;
    getMemory(&str, 100);
    strcpy(str, "hello");
    cout << str << endl;
    return 0;
}
Copy the code

But this is a little bit troublesome to write, we can directly return the requested memory.

#include<iostream>
#include<cstring>
using namespace std;

char* getMemory(int num)
{
    return (char*)malloc(sizeof(char) * num);
}

int main(int argc, const char* argv[])
{
    char *str = NULL;
    str = getMemory(100);
    strcpy(str, "hello");
    cout << str << endl;
    return 0;
}
Copy the code

Example 2: What’s wrong with this function?

char* strA()
{
    char str[] = "hello world";
    return str;
}
Copy the code

The address stored in STR is the first address of “Hello world” in strA. When the call is complete, the temporary space is reset.

To get the correct function, write:

char* strA()
{
    char *str = "hello world";
    return str;
}
Copy the code

Char STR [], char* STR,

Char STR [] allocates a local array,

Char * STR assigns a pointer traversal,

Local arrays are local variables that correspond to stacks in memory. Pointer variables are global variables that correspond to global regions in memory.

However, the above code can only be written in C, c++ does not allow

ISO C++ forbids converting a string constant to 'char*'

It could be written like this:

char* strA()
{
    static char str[] = "hello world";
    return str;
}
Copy the code

Example 3: What is the output of the following code?

#include<iostream> using namespace std; class A { public: A() { m_a = 1; m_b = 2; } ~A(){} void fun() { printf("%d%d", m_a, m_b); } private: int m_a; int m_b; }; class B { public: B() {m_c = 3; } ~B(); void fun() {printf("%d", m_c); } private: int m_c; }; int main(int argc, const char* argv[]) { A a; B *pb = (B*)(&a); pb->fun(); return 0; }Copy the code

The purpose of this problem is to test your understanding of memory offset,

B* pb = (B*)(&a); , this is a brutal conversion, forcing a address content as a class B object, pb points to the memory space of class A, class A space according to the structure of class B to read.

A function pointer

Example 1: Find the following program error

#include<iostream>
using namespace std;

int Max(int x, int y)
{
	return x > y ? x : y;
}

int main(int argc, char const *argv[])
{
	int *p = &Max;
	cout << p(2, 1) << endl;
	return 0;
}
Copy the code

Int (*p)(int, int) = &max;

Int *p p is a pointer to int

Int *p(int, int), p is a function that returns int*

Int (*p)(int, int), p is a pointer to the address of a function that returns int

Example 2: What do the following data declarations represent?

float(**def)[10];
double*(*gh)[10];
double(*f[10])();
int*((*b)[10]);
long(*fun)(int)
int(*(*F)(int, int))(int)
Copy the code

Here are the answers:

float(**def)[10]; // def is a double*(*gh)[10]; // def is a double*(*gh)[10]; // gh is a one-level pointer to an array of size 10. The element type is double* double(*f[10])(); Int *((*b)[10]); int*((*b)[10]); Int * long(*fun)(int); // Fun is a pointer to a function pointer, Int (*(*F)(int, int))(int) // F is a pointer to a function that takes (int, int) and returns a pointer to a function, The function takes an argument of (int) and returns an intCopy the code

Pointer arrays and array Pointers

Example 1: What is the output of the following program?

#include<iostream> using namespace std; Int main (int arg c, char * const argv []) {int v [2] [10] = {,2,3,4,5,6,7,8,9,10 {1}, {11,12,13,14,15,16,17,18,19,20}}; int (*a)[10] = v; // Array pointer is a second level pointer cout << a << endl; / / a is a pointer to,2,3,4,5,6,7,8,9,10 {1} cout < < * a < < endl; Cout << **a << endl; Cout << a + 1 << endl; / / pointer offset a backward position, the position for the size of the pointer refers to the capacity, the length of the offset point after 11,12,13,14,15,16,17,18,19,20} {cout < < "* (a + 1) < < endl; Cout << **(a + 1) << endl; Cout << *a + 1 << endl; Cout << *(*a+1) << endl; cout << (*a+1) << endl; // return 0; }Copy the code

Example 2: Use variable A to give the following definition

  1. An integer.

  2. A pointer to an integer.

  3. A pointer to a pointer that points to an integer

  4. An array of 10 integers

  5. An array of 10 Pointers to an integer

  6. A pointer to a set of 10 integers

  7. A pointer to a function that takes an integer and returns an integer

  8. An array of 10 Pointers to a function that takes an integer argument and returns an integer

The answer:

// 1
int a;
// 2
int *a;
// 3
int **a;
// 4
int a[10];
// 5
int *a[10];
// 6
int (*a)[10];
// 7
int (*a)(int);
// 8
int (*a[10])(int);
Copy the code

Example 3: Write the output of the following program fragment

Int a [] = {1, 2, 3, 4, 5}; int *ptr = (int*)(&a + 1); printf("%d %d", *(a+1), *(ptr - 1));Copy the code

The answer:

#include<iostream> #include<cstdio> using namespace std; Int main(int argc, char const *argv[]) {int a[] = {1,2,3,4,5}; int *ptr = (int*)(&a + 1); cout << a << endl; // A constant pointer to the array element cout << &a << endl; Cout << a + 1 << endl; cout << a + 1 << endl; cout << &a + 1 << endl; // &a +1 should point to the next element of 5, ptr-1 points to 5 printf("%d %d", *(a+1), *(ptr-1)); return 0; }Copy the code

Stray pointer and wild pointer

Stray Pointers

The pointer points to a memory that is reclaimed, but the pointer is not set to null

Wild pointer

: a pointer was declared but not initialized.

Example 1: What is the output of the following program?

#include<iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    char s1[] = "hello";
    char s2[] = "the";
    char s3[] = "world";
    char* a[] = {s1, s2, s3};
    char **pa = a;
    pa++;
    cout << *pa << endl;
    return 0;
}
Copy the code

A is a constant pointer to the beginning of the array, pa++, move it back one pointer size, point to s2, print “the”

Pointer and handle

Handle is an integer, an operating system maintenance of an object in memory, physical memory address list of integer index, because when the operating system memory management often release the current free object memory, when need to access again submitted to physical memory, so the object is physical address change, do not allow the program directly through the physical address to access the object. The program will want to access the object of the handle to the system, the system according to the handle to retrieve their own maintenance of the object list can know the program want to access the object and its physical address.

A handle is a pointer to a pointer. We know that a pointer is a memory address in which the objects that make up the program reside after the application is started. If simple, it seems that we only need to know the first address of memory, then we can access objects with that address at any time. However, if you really think so, then it is a big mistake, we know that the operating system is a virtual memory based, there is page feed phenomenon, object moving means its address changes, if the address always changes, how do we find the object? In order to solve this problem, the operating system sets aside some memory address for each application program, which is used to register the change of the address of each application object in memory. The registered address is unchanged. After the operating system moves the object, it tells the address of the object to the handle, through which the specific location of the object can be known.

Handle –> Address of register object address –> address of object –> object

Each time the program is restarted, the system does not guarantee that the handle assigned to the program will be the same, just like going to the movie theater and selling us a different seat each time.

This pointer

There is a description of the this pointer: When you enter a house, you can see tables, chairs, etc., but you cannot see the full picture

For an instance of a class, you can see member functions, member variables, but what about the instance itself? The this pointer is such a pointer, pointing to the instance itself at all times

  1. The this pointer is essentially a function argument, just a syntactic argument hidden by the compiler. In fact, member functions default to T* const this as their first argument

  2. This is constructed before the start of a member function and cleared after the end.

a.func(10); Will be compiled by the compiler to A::func(& A, 10); , which looks the same as a static function, but there are some differences. The compiler usually optimizes this pointer, which is passed efficiently. For example, VC is usually passed through the ECX register.

  1. The this pointer does not occupy object space. This is an implicit argument to a nonstatic member function.

  2. Where is the this pointer stored? The this pointer may be in a heap, stack, or register, depending on the compiler.

  3. How is the this pointer passed to a function in a class? Most compilers pass this pointer through the ECX register. In fact, this is an unwritten rule. In general, different compilers follow the same rules for passing arguments, otherwise the obJ produced by different compilers will not match

  4. If we know the position of this object, can we use it directly?

The this pointer is defined only in member functions. Therefore, once you get an object, you can’t use the this pointer through the object, only in member functions