文章目录
Pointers
-
To declare a pointer,
int* p
和int *p
皆可,但是int* p, q
表示p
为指针,q
为int
型变量,如果要在一行里定义多个指针,int *p, *q
. Use this to initialize pointerint* aPtr = &a;
-
Require to include letter
Ptr
in each pointer variable name to make it clear that variable is a pointer. -
nullptr
is null pointer, initialize all pointers to prevent pointing to unknown or uninitialized areas of memory. Prior to C++11,0
orNULL
is equivalent otnullptr
. -
Dereferencing an uninitialized pointer results in undefined behavior that could cause a fatal execution-time error. This could also lead to accidentally modifying important data, allowing the program to run to completion, possibly with incorrect results.
-
Dereferencing a null pointer results in undefined behavior and typically causes a fatal execution-time error. Ensure that a pointer is not null before dereferencing it.
-
Operator precedence
-
Insight: Pass-By-Reference with a Pointer Actually Passes the Pointer By Value
Built-in Array
-
Initializing Built-in Arrays.
int n[5]{1, 2, 3, 4, 5};
If only give4
elements, the rest of them are set to default value,0
forint
,false
forbool
, andnullptr
for Pointer. -
arrayName
is implicitly convertible to&arrayName[0]
. -
Applying the
const
type qualifier to a built-in array parameter in a
function definition to prevent the original built-in array from being modified in the function body is another example of the principle of least privilege. Functions should not be given the capability to modify a built-in array unless it’s absolutely necessary. -
Built-in array do not know its size.
-
Limitations of Built-in Arrays (IMPORTANT)
- They cannot be compared using the relational and equality operators – you must use a loop to compare two built-in arrays element by element.
- They cannot be assigned to one another – an array name is effectively a pointer that is const .
- They don’t know their own size -— a function that processes a built- in array typically receives both the built-in array’s name and its size as arguments.
- They don’t provide automatic bounds checking —- you must ensure that array-access expressions use subscripts that are within the built-in array’s bounds.
-
In modern C++, should use
array
orvector
objects to represent lists and tables of values. However, there are cases that we should use built-in array, for example, the command-line arguments. -
If a value does not (or should not) change in the body of a function to which it’s passed, the parameter should be declared
const
. For exampleint sumElements(const int* values, const size_t numberOfElements)
orint sumElements(const int[] values, const size_t numberOfElements)
. -
object
likearray
,vector
are passed by value, thebuilt-in array
are passed by pointer. -
Use pass-by-value to pass fundamental-type arguments(
int
,double
), unless the called function are required to be able to directly modify the value in the caller.
Using const
with Pointers
There are four ways to pass a pointer to a function:
- a non-constant pointer to non-constant data,
- a non-constant pointer to constant data,
- a constant pointer to non-constant data
- a constant pointer to constant data
Non-constant Pointer to Non-constant Data
- the data can be modified through the dereferenced pointer
- and the pointer can be modified to point to other data
Highest access is granted, e.g.int* countPrt
.
Non-constant Pointer to Constant Data
- a pointer that can be modified to point to any data of the appropriate type, but
- the data to which it points cannot be modified through the pointer.
Such a pointer might be used to receive a built-in array argument to a function that should be allowed to read the elements, but not modify them. Any attempt to modify the data in the function result in a compilation error.
E.g. const int* countPtr;
Read from right to left,
countPtr
is a pointer to an integer constant.
Also, int const* countPtr;
const
applies to theint
, not the pointer. Read from right to left,countPtr
is a pointer to a constant integer.
Constant Pointer to Non-constant Data
- always points to the same memory location, and
- the data at that location can be modified through the pointer.
Pointer that are declared const
must be initialized when they are declared, but if the pointer is a function parameter, it’s initialized with the pointer that’s passed to the function.
E.g. int* const countPtr;
,
Read from right to left,
countPtr
is a constant pointer to a non-constant integer.
Constant Pointer to Constant Data
Minimum access privilege.
- such a pointer always points to the same memory location, and
- the data at that location cannot be modified via the pointer.
This is how a built-in array should be passed to a function that only reads from the array, using array subscript notation, and does not modify it.
E.g. const int* const ptr{&x};
Pointer Arithmetic
-
Pointer arithmetic is meaningful only on a pointer that points to a built-in array.
-
We cannot assume that two variables of the same type are stored contiguously in memory unless they’re adjacent elements of a built-in array.
-
A pointer can be assigned to another pointer if both pointers are of the same type. Except that
void*
is a generic pointer capable of representing any pointer. -
Different pointer assignment need
reinterpret_cast
. -
Cannot dereference a
void*
. -
Pointer comparisons compare the addresses stored in the pointers.
-
Pointer value is
0
meansnullptr
. -
Array name
a
declared asint a[]
is const, cannot change, likea += 3
is not permitted.*(a + 3)
, anda[3]
means the third element in array.
Pointer Based String
-
character constants, single quota. string literals, string constants use double quota.
-
String literal initializers
char color[]{"blue"}; const char* colorPtr{"blue"}; const char[] color{'b', 'l', 'u', 'e', '\0'};
-
String literals exist for the duration of the program and may be shared if the same string literal is referenced from multiple locations in a program. String literals cannot be modified.
-
Not allocating sufficient space in a built-in array of char s to store the null character that terminates a string is a logic error.
-
Creating or using a C string that does not contain a terminating null character can lead to logic errors.
-
Reading and displaying c-style strings.
-
One common error
void func() { const char c[]{'1', '2', '3'}; cout << "in func(), c = " << c << endl; } int main() { func(); }
The output will start with
123
and end with the'\0'
in the memory.in func(), c = 123@iZ��
This is because the miss of
\0
in the char array. We use initialize a char array with\0
to terminate the string.