Projects记录C++

[C++重点]Pointers

2021-01-04  本文已影响0人  greatseniorsde

好久没用C++了,复习一下基础知识。

Address-of operator (&)

foo = &myvar;
This would assign the address of variable myvar to foo; by preceding the name of the variable myvar with the address-of operator (&), we are no longer assigning the content of the variable itself to foo, but its address.
In this case, consider the following code fragment:

myvar = 25;
foo = &myvar;
bar = myvar;

The values contained in each variable after the execution of this are shown in the following diagram:

image.png

The variable that stores the address of another variable (like foo in the previous example) is what in C++ is called a pointer.

Dereference operator (*)

An interesting property of pointers is that they can be used to access the variable they point to directly. This is done by preceding the pointer name with the dereference operator (*). The operator itself can be read as "value pointed to by".
baz = *foo;

This could be read as: "baz equal to value pointed to by foo", and the statement would actually assign the value 25 to baz, since foo is 1776, and the value pointed to by 1776 (following the example above) would be 25.

image.png

The reference and dereference operators are thus complementary:
& is the address-of operator, and can be read simply as "address of"

Thus, they have sort of opposite meanings: An address obtained with & can be dereferenced with *.
Earlier, we performed the following two assignment operations:

myvar = 25;
foo = &myvar;

Right after these two statements, all of the following expressions would give true as result:

myvar == 25
&myvar == 1776
foo == 1776
*foo == 25

Declaring pointers

he declaration of pointers follows this syntax:

type * name;

where type is the data type pointed to by the pointer. This type is not the type of the pointer itself, but the type of the data the pointer points to. For example:

int * number;
char * character;
double * decimals;

Let's see an example on pointers:

// my first pointer
#include <iostream>
using namespace std;

int main ()
{
  int firstvalue, secondvalue;
  int * mypointer;

  mypointer = &firstvalue;
  *mypointer = 10;
  mypointer = &secondvalue;
  *mypointer = 20;
  cout << "firstvalue is " << firstvalue << '\n';
  cout << "secondvalue is " << secondvalue << '\n';
  return 0;
}
firstvalue is 10
secondvalue is 20</samp></pre>

Here is an example a little bit more elaborated:

// more pointers
#include <iostream>
using namespace std;

int main ()
{
  int firstvalue = 5, secondvalue = 15;
  int * p1, * p2;

  p1 = &firstvalue;  // p1 = address of firstvalue
  p2 = &secondvalue; // p2 = address of secondvalue
  *p1 = 10;          // value pointed to by p1 = 10
  *p2 = *p1;         // value pointed to by p2 = value pointed to by p1
  p1 = p2;           // p1 = p2 (value of pointer is copied)
  *p1 = 20;          // value pointed to by p1 = 20
  
  cout << "firstvalue is " << firstvalue << '\n';
  cout << "secondvalue is " << secondvalue << '\n';
  return 0;
}
firstvalue is 10
secondvalue is 20

其中容易错的是p1 = p2这句assignment:

Pointer assignment between two pointers makes them point to the same pointee. So the assignment y = x; makes y point to the same pointee as x. Pointer assignment does not touch the pointees. It just changes one pointer to have the same reference as another pointer. After pointer assignment, the two pointers are said to be "sharing" the pointee.
p1 = p2 则p1 points to the pointee p2 points to. 相当于p1 = &secondvalue.
翻译一下就是

  p1 = &firstvalue;  // p1 = address of firstvalue
  p2 = &secondvalue; // p2 = address of secondvalue
  firstvalue = 10;         
  secondvalue = firstvalue = 10;        
  p1 = &secondvalue;          
  secondvalue = 20;         
  

so we get firstvalue = 10; secondvalue = 20;

Pointers and arrays

Normally, we obtain a pointer to an object by using the address-of operator &, Generally speaking, the address-of operator may be applied to any object. The elements in an array are objects. When we subscript an array, the result is the object at that location in the array. As with any other object, we can obtain a pointer to an array element by taking the address of that element:

string nums[] = {"one", "two", "three"}; // array of strings 
string *p = &nums[0]; // p points to the first element in nums

Aarrays have a special property—in most places when we use an array, the compiler automatically substitutes a pointer to the first element:

string *p2 = nums; // equivalent to p2 = &nums[0]

Let's see an example that mixes arrays and pointers:

// more pointers
#include <iostream>
using namespace std;

int main ()
{
  int numbers[5];
  int * p;
  p = numbers;  *p = 10;
  p++;  *p = 20;
  p = &numbers[2];  *p = 30;
  p = numbers + 3;  *p = 40;
  p = numbers;  *(p+4) = 50;
  for (int n=0; n<5; n++)
    cout << numbers[n] << ", ";
  return 0;
}

Pointers and arrays support the same set of operations, with the same meaning for both. The main difference being that pointers can be assigned new addresses, while arrays cannot.
In the chapter about arrays, brackets ([]) were explained as specifying the index of an element of the array. Well, in fact these brackets are a dereferencing operator known as offset operator. They dereference the variable they follow just as * does, but they also add the number between brackets to the address being dereferenced. For example:

a[5] = 0;       // a [offset of 5] = 0
*(a+5) = 0;     // pointed to by (a+5) = 0  

These two expressions are equivalent and valid, not only if a is a pointer, but also if a is an array. Remember that if an array, its name can be used just like a pointer to its first element.

Pointer arithmetics

When we add (or subtract) an integral value to (or from) a pointer, the result is a new pointer. That new pointer points to the element the given number ahead of (or behind) the original pointer:

constexpr size_t sz = 5;
int arr[sz] = {1,2,3,4,5}; 
int *ip = arr; // equivalent to int *ip = &arr[0] 
int *ip2 = ip + 4; // ip2 points to arr[4], the last element in arr

The result of adding 4 to ip is a pointer that points to the element four elements further on in the array from the one to which ip currently points.
The result of adding an integral value to a pointer must be a pointer to an element in the same array, or a pointer just past the end of the array:

// ok: arr is converted to a pointer to its first element; p points one past the end of arr 
int *p = arr + sz; // use caution -- do not dereference!
int *p2 = arr + 10; // error: arr has only 5 elements; p2 has undefined value

As with iterators, subtracting two pointers gives us the distance between those pointers. The pointers must point to elements in the same array:

auto n = end(arr) - begin(arr); // n is 5, the number of elements in arr

We can use the relational operators to compare pointers that point to elements of an array, or one past the last element in that array. For example, we can traverse the elements in arr as follows:

int *b = arr, *e = arr + sz; 
while (b < e) {
 // use *b
   ++b; 
}

Void pointers

The type void* is a special pointer type that can hold the address of any object. Like any other pointer, a void* pointer holds an address, but the type of the object at that address is unknown:

double obj = 3.14, 
*pd = &obj; // ok: void* can hold the address value of any data pointer type void 
*pv = &obj; // obj can be an object of any type // pv can hold a pointer to any type

Null pointers

A null pointer does not point to any object. Code can check whether a pointer is null before attempting to use it. There are several ways to obtain a null pointer:

int *p1 = nullptr; // equivalent to int *p1 = 0; 
int *p2 = 0; // directly initializes p2 from the literal constant 0 
int *p3 = NULL; // equivalent to int *p3 = 0; // must #include cstdlib 

It is illegal to assign an int variable to a pointer, even if the variable’s value happens to be 0.

int zero = 0; pi = zero; // error: cannot assign an int to a pointer

Pointer initialization

When pointers are initialized, what is initialized is the address they point to (i.e., myptr), never the value being pointed (i.e., *myptr).
Pointers can be initialized either to the address of a variable (such as in the case above), or to the value of another pointer (or array):

int myvar;
int *foo = &myvar;
int *bar = foo;

Source:

Official tutorial
C++ Primer 5th Edition

上一篇下一篇

猜你喜欢

热点阅读