what happens to initialize pointers at end of function c++

C++ Programming Language

Pointers, References and Dynamic Retentivity Allotment

Pointers, References and Dynamic Memory Allotment are the almost powerful features in C/C++ language, which allows programmers to directly manipulate retention to efficiently manage the memory - the most disquisitional and scarce resource in computer - for best operation. Nevertheless, "arrow" is also the most complex and difficult feature in C/C++ language.

Pointers are extremely powerful because they allows you to admission addresses and manipulate their contents. But they are likewise extremely complex to handle. Using them correctly, they could greatly amend the efficiency and operation. On the other mitt, using them incorrectly could atomic number 82 to many problems, from un-readable and un-maintainable codes, to infamous bugs such as retentiveness leaks and buffer overflow, which may expose your system to hacking. Many new languages (such as Java and C#) remove pointer from their syntax to avoid the pitfalls of pointers, by providing automated memory management.

Although you lot can write C/C++ programs without using pointers, however, information technology is difficult not to mention pointer in instruction C/C++ linguistic communication. Arrow is probably not meant for novices and dummies.

Arrow Variables

A computer memory location has an address and holds a content. The address is a numerical number (ofttimes expressed in hexadecimal), which is difficult for programmers to use directly. Typically, each accost location holds 8-fleck (i.e., one-byte) of data. It is entirely up to the developer to interpret the meaning of the data, such equally integer, existent number, characters or strings.

To ease the burden of programming using numerical address and developer-interpreted information, early on programming languages (such as C) innovate the concept of variables. A variable is a named location that can store a value of a item type. Instead of numerical addresses, names (or identifiers) are attached to certain addresses. Also, types (such equally int, double, char) are associated with the contents for ease of estimation of information.

Each address location typically concur viii-flake (i.e., ane-byte) of information. A 4-byte int value occupies iv memory locations. A 32-bit system typically uses 32-bit addresses. To shop a 32-chip address, 4 memory locations are required.

The post-obit diagram illustrate the relationship between computers' retention accost and content; and variable'south name, type and value used past the programmers.

MemoryAddressContent.png

Pointer Variables (or Pointers)

A arrow variable (or pointer in brusque) is basically the aforementioned as the other variables, which can store a piece of data. Dissimilar normal variable which stores a value (such as an int, a double, a char), a arrow stores a memory address.

Declaring Pointers

Pointers must be declared before they can be used, just like a normal variable. The syntax of declaring a pointer is to place a * in front of the name. A arrow is associated with a type (such as int and double) too.

          type          *ptr;              type*          ptr;           type          *          ptr;        

For case,

int * iPtr;                       double * dPtr;        

Take notation that you demand to place a * in forepart of each pointer variable, in other words, * applies only to the name that followed. The * in the declaration statement is not an operator, but indicates that the name followed is a pointer variable. For example,

int *p1, *p2, i;     int* p1, p2, i;      int * p1, * p2, i;        

Naming Convention of Pointers: Include a "p" or "ptr" equally prefix or suffix, eastward.1000., iPtr, numberPtr, pNumber, pStudent.

Initializing Pointers via the Accost-Of Operator (&)

When you lot declare a pointer variable, its content is non initialized. In other words, information technology contains an address of "somewhere", which is of grade not a valid location. This is dangerous! Y'all need to initialize a pointer past assigning it a valid address. This is normally done via the address-of operator (&).

The accost-of operator (&) operates on a variable, and returns the address of the variable. For instance, if number is an int variable, &number returns the address of the variable number.

You can use the address-of operator to get the address of a variable, and assign the address to a pointer variable. For example,

int number = 88;      int * pNumber;                 pNumber = &number;             int * pAnother = &number;        

PointerDeclaration.png

As illustrated, the int variable number, starting at address 0x22ccec, contains an int value 88. The expression &number returns the address of the variable number, which is 0x22ccec. This address is and so assigned to the arrow variable pNumber, as its initial value.

The address-of operator (&) can merely be used on the RHS.

Indirection or Dereferencing Operator (*)

The indirection operator (or dereferencing operator) (*) operates on a pointer, and returns the value stored in the address kept in the arrow variable. For case, if pNumber is an int pointer, *pNumber returns the int value "pointed to" by pNumber.

For example,

int number = 88; int * pNumber = &number;   cout << pNumber<< endl;    cout <<          *pNumber          << endl;  *pNumber          = 99;             cout <<          *pNumber          << endl;  cout << number << endl;        

Have note that pNumber stores a retention address location, whereas *pNumber refers to the value stored in the address kept in the pointer variable, or the value pointed to by the arrow.

Every bit illustrated, a variable (such as number) direct references a value, whereas a pointer indirectly references a value through the memory address it stores. Referencing a value indirectly via a pointer is chosen indirection or dereferencing.

The indirection operator (*) can be used in both the RHS (temp = *pNumber) and the LHS (*pNumber = 99) of an assignment statement.

Accept annotation that the symbol * has different meaning in a declaration argument and in an expression. When it is used in a declaration (e.grand., int * pNumber), it denotes that the name followed is a pointer variable. Whereas when information technology is used in a expression (e.grand., *pNumber = 99 ; temp << *pNumber;), it refers to the value pointed to by the pointer variable.

Pointer has a Type As well

A pointer is associated with a type (of the value information technology points to), which is specified during proclamation. A pointer tin can just hold an address of the declared type; it cannot hold an address of a different type.

int i = 88; double d = 55.66; int * iPtr = &i;     double * dPtr = &d;    iPtr = &d;          // ERROR, cannot hold accost of different type          dPtr = &i;          // Mistake          iPtr = i;          // Error, pointer holds address of an int, Not int value          int j = 99; iPtr = &j;        
Example
1 2 iii iv 5 6 seven eight nine 10 xi 12 13 xiv 15 16 17 18 nineteen xx 21 22 23
                    #include <iostream> using namespace std;   int main() {    int number = 88;        int * pNumber;          pNumber = &number;        cout << pNumber << endl;      cout << &number << endl;      cout << *pNumber << endl;     cout << number << endl;         *pNumber = 99;                cout << pNumber << endl;      cout << &number << endl;      cout << *pNumber << endl;     cout << number << endl;                                       cout << &pNumber << endl;  }

Notes: The address values that you get are unlikely to be the aforementioned as mine. The Os loads the program in available free memory locations, instead of fixed memory locations.

Uninitialized Pointers

The following code fragment has a serious logical error!

int * iPtr; *iPtr = 55; cout << *iPtr << endl;

The arrow iPtr was declared without initialization, i.e., it is pointing to "somewhere" which is of course an invalid memory location. The *iPtr = 55 corrupts the value of "somewhere"! Yous need to initialize a pointer past assigning it a valid address. Virtually of the compilers does not signal an mistake or a warning for uninitialized arrow?!

Goose egg Pointers

You can initialize a pointer to 0 or NULL, i.e., information technology points to nothing. It is called a nil pointer. Dereferencing a zippo arrow (*p) causes an STATUS_ACCESS_VIOLATION exception.

int * iPtr = 0;          cout <<          *iPtr          << endl;          // ERROR! STATUS_ACCESS_VIOLATION exception          int * p = NULL;        

Initialize a pointer to null during declaration is a good software applied science practice.

C++11 introduces a new keyword called nullptr to represent null pointer.

Reference Variables

C++ added the so-called reference variables (or references in brusk). A reference is an alias, or an alternate name to an existing variable. For example, suppose you make peter a reference (alias) to paul, you tin can refer to the person as either peter or paul.

The master apply of references is acting as function formal parameters to support laissez passer-by-reference. In an reference variable is passed into a function, the function works on the original copy (instead of a clone re-create in pass-past-value). Changes inside the part are reflected exterior the function.

A reference is like to a pointer. In many cases, a reference can be used equally an alternative to arrow, in particular, for the role parameter.

References (or Aliases) (&)

Recall that C/C++ use & to denote the address-of operator in an expression. C++ assigns an additional meaning to & in announcement to declare a reference variable.

The meaning of symbol & is different in an expression and in a declaration. When it is used in an expression, & denotes the address-of operator, which returns the address of a variable, e.one thousand., if number is an int variable, &number returns the address of the variable number (this has been described in the in a higher place section).

Howeve, when & is used in a declaration (including function formal parameters), information technology is role of the type identifier and is used to declare a reference variable (or reference or alias or alternate name). It is used to provide another name, or some other reference, or alias to an existing variable.

The syntax is equally follow:

          blazon          &newName          =          existingName;           type&          newName          =          existingName;           type          &          newName          =          existingName;        

It shall exist read as " newName is a reference to exisitngName ", or " newNew is an alias of existingName ". You can at present refer to the variable equally newName or existingName .

For instance,

1 2 3 4 5 half-dozen 7 eight 9 10 11 12 13 xiv fifteen 16 17 xviii 19 20
                    #include <iostream> using namespace std;   int main() {    int number = 88;                            int & refNumber = number;                                                      cout << number << endl;        cout <<                  refNumber                  << endl;                   refNumber = 99;                cout <<                  refNumber                  << endl;    cout << number << endl;          number = 55;                   cout << number << endl;    cout <<                  refNumber                  << endl;  }

PointerReferencing.png

How References Piece of work?

A reference works as a pointer. A reference is alleged as an alias of a variable. It stores the address of the variable, as illustrated:

ReferenceIsAPointer.png

References vs. Pointers

Pointers and references are equivalent, except:

  1. A reference is a proper noun constant for an address. You need to initialize the reference during annunciation.
                  int & iRef;            
    Once a reference is established to a variable, you cannot change the reference to reference another variable.
  2. To get the value pointed to by a pointer, you need to employ the dereferencing operator * (east.g., if pNumber is a int pointer, *pNumber returns the value pointed to by pNumber. It is chosen dereferencing or indirection). To assign an accost of a variable into a pointer, y'all need to employ the address-of operator & (due east.g., pNumber = &number).
    On the other hand, referencing and dereferencing are done on the references implicitly. For instance, if refNumber is a reference (alias) to some other int variable, refNumber returns the value of the variable. No explicit dereferencing operator * should be used. Furthermore, to assign an address of a variable to a reference variable, no address-of operator & is needed.

For example,

1 two three 4 five 6 7 8 9 10 11 12 thirteen 14 xv 16 17 18 xix 20 21 22 23 24 25 26 27 28 29 30 31
                    #include <iostream> using namespace std;   int master() {    int number1 = 88, number2 = 22;         int * pNumber1 = &number1;     *pNumber1 = 99;                cout << *pNumber1 << endl;     cout << &number1 << endl;      cout << pNumber1 << endl;      cout << &pNumber1 << endl;     pNumber1 = &number2;                int & refNumber1 = number1;     refNumber1 = 11;                cout << refNumber1 << endl;     cout << &number1 << endl;       cout << &refNumber1 << endl;                                       refNumber1 = number2;                                             number2++;       cout << refNumber1 << endl;      cout << number1 << endl;         cout << number2 << endl;      }

A reference variable provides a new name to an existing variable. It is dereferenced implicitly and does not need the dereferencing operator * to think the value referenced. On the other manus, a pointer variable stores an address. You can alter the address value stored in a pointer. To retrieve the value pointed to by a pointer, you need to use the indirection operator *, which is known as explicit dereferencing. Reference can exist treated as a const pointer. Information technology has to exist initialized during proclamation, and its content cannot exist inverse.

Reference is closely related to pointer. In many cases, information technology tin can exist used as an alternative to pointer. A reference allows y'all to manipulate an object using pointer, but without the arrow syntax of referencing and dereferencing.

The in a higher place example illustrates how reference works, but does not testify its typical usage, which is used as the function formal parameter for pass-by-reference.

Pass-By-Reference into Functions with Reference Arguments vs. Arrow Arguments

Pass-past-Value

In C/C++, by default, arguments are passed into functions by value (except arrays which is treated every bit pointers). That is, a clone copy of the argument is made and passed into the function. Changes to the clone copy inside the function has no upshot to the original argument in the caller. In other words, the called role has no access to the variables in the caller. For example,

one 2 3 iv 5 half-dozen seven 8 9 10 11 12 thirteen 14 15 16 17 18 nineteen
                    #include <iostream> using namespace std;   int square(int);   int main() {    int number = 8;    cout <<  "In main(): " << &number << endl;     cout << number << endl;            cout << square(number) << endl;    cout << number << endl;         }   int foursquare(int n) {      cout <<  "In foursquare(): " << &n << endl;     n *= northward;           return n; }

The output clearly shows that there are two different addresses.

Pass-by-Reference with Pointer Arguments

In many situations, we may wish to modify the original copy directly (peculiarly in passing huge object or array) to avoid the overhead of cloning. This can be washed by passing a pointer of the object into the office, known every bit pass-by-reference. For example,

1 2 iii iv five 6 7 eight ix 10 11 12 13 fourteen 15 sixteen 17 18
                    #include <iostream> using namespace std;   void square(int *);   int master() {    int number = 8;    cout <<  "In primary(): " << &number << endl;     cout << number << endl;      foursquare(&number);             cout << number << endl;   }   void foursquare(int * pNumber) {     cout <<  "In square(): " << pNumber << endl;                   *pNumber                  *=                  *pNumber;      }

The called role operates on the same address, and can thus modify the variable in the caller.

Pass-by-Reference with Reference Arguments

Instead of passing pointers into role, you lot could too laissez passer references into function, to avoid the clumsy syntax of referencing and dereferencing. For instance,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 eighteen
                    #include <iostream> using namespace std;   void square(int &);   int principal() {    int number = viii;    cout <<  "In principal(): " << &number << endl;     cout << number << endl;     square(number);             cout << number << endl;  }   void foursquare(int & rNumber) {     cout <<  "In foursquare(): " << &rNumber << endl;                   rNumber                  *=                  rNumber;        }

Again, the output shows that the called function operates on the aforementioned address, and can thus alter the caller's variable.

Take note referencing (in the caller) and dereferencing (in the office) are washed implicitly. The only coding difference with pass-by-value is in the function's parameter announcement.

Call back that references are to exist initialized during proclamation. In the case of role formal parameter, the references are initialized when the function is invoked, to the caller's arguments.

References are primarily used in passing reference in/out of functions to allow the chosen office accesses variables in the caller directly.

"const" Function Reference/Arrow Parameters

A const part formal parameter cannot exist modified within the function. Use const whenever possible as it protects you from inadvertently modifying the parameter and protects you against many programming errors.

A const function parameter can receive both const and not-const argument. On the other hand, a non-const function reference/arrow parameter can only receive non-const statement. For example,

i ii three 4 5 6 vii viii 9 ten 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 forty 41 42
                    #include <iostream> using namespace std;   int squareConst(const int); int squareNonConst(int); int squareConstRef(const int &); int squareNonConstRef(int &);   int master() {    int number = 8;    const int constNumber = 9;    cout << squareConst(number) << endl;    cout << squareConst(constNumber) << endl;    cout << squareNonConst(number) << endl;    cout << squareNonConst(constNumber) << endl;      cout << squareConstRef(number) << endl;    cout << squareConstRef(constNumber) << endl;    cout << squareNonConstRef(number) << endl;                  cout << squareNonConstRef(constNumber) << endl;                          }   int squareConst(const int number) {                      number *= number;                      return number * number; }   int squareNonConst(int number) {     number *= number;    return number; }   int squareConstRef(const int & number) {     return number * number; }   int squareNonConstRef(int & number) {     return number * number; }

Passing the Function'due south Return Value

Passing the Return-value equally Reference

You can also laissez passer the return-value as reference or arrow. For example,

ane 2 3 4 5 six 7 viii 9 10 11 12 xiii xiv fifteen sixteen 17 eighteen 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
                    #include <iostream> using namespace std;   int & squareRef(int &); int * squarePtr(int *);   int main() {    int number1 = 8;    cout <<  "In main() &number1: " << &number1 << endl;     int & upshot = squareRef(number1);    cout <<  "In principal() &result: " << &result << endl;     cout << effect << endl;      cout << number1 << endl;       int number2 = 9;    cout <<  "In main() &number2: " << &number2 << endl;     int * pResult = squarePtr(&number2);    cout <<  "In main() pResult: " << pResult << endl;     cout << *pResult << endl;      cout << number2 << endl;    }   int & squareRef(int & rNumber) {    cout <<  "In squareRef(): " << &rNumber << endl;     rNumber *= rNumber;    render rNumber; }   int * squarePtr(int * pNumber) {    cout <<  "In squarePtr(): " << pNumber << endl;     *pNumber *= *pNumber;    return pNumber; }
Y'all should not laissez passer Function'south local variable equally return value by reference
1 2 3 iv 5 6 7 viii 9 10 11 12 13 xiv fifteen xvi 17 eighteen 19 20 21 22 23 24 25
                    #include <iostream> using namespace std;   int * squarePtr(int); int & squareRef(int);   int main() {    int number = viii;    cout << number << endl;     cout << *squarePtr(number) << endl;     cout << squareRef(number) << endl;   }   int * squarePtr(int number) {    int localResult = number * number;    render &localResult;       }   int & squareRef(int number) {    int localResult = number * number;    return localResult;       }

This program has a serious logical error, as local variable of function is passed back equally return value by reference. Local variable has local scope within the function, and its value is destroyed after the function exits. The GCC compiler is kind enough to issue a warning (only not fault).

It is safe to render a reference that is passed into the function equally an argument. Come across earlier examples.

Passing Dynamically Allocated Memory as Return Value by Reference

Instead, yous need to dynamically allocate a variable for the return value, and return it by reference.

i 2 3 four v half dozen 7 8 9 10 11 12 13 14 xv 16 17 18 19 xx 21 22 23
                    #include <iostream> using namespace std;   int * squarePtr(int); int & squareRef(int);   int main() {    int number = 8;    cout << number << endl;     cout << *squarePtr(number) << endl;     cout << squareRef(number) << endl;   }   int * squarePtr(int number) {    int * dynamicAllocatedResult = new int(number * number);    return dynamicAllocatedResult; }   int & squareRef(int number) {    int * dynamicAllocatedResult = new int(number * number);    render *dynamicAllocatedResult; }

Summary

Pointers and references are highly complex and hard to master. Only they tin greatly amend the efficiency of the programs.

For novices, avoid using pointers in your plan. Improper usage can lead to serious logical bugs. However, you need to understand the syntaxes of pass-past-reference with pointers and references, because they are used in many library functions.

  • In pass-by-value, a clone is fabricated and passed into the function. The caller's copy cannot be modified.
  • In pass-by-reference, a pointer is passed into the part. The caller'southward copy could exist modified within the function.
  • In pass-past-reference with reference arguments, you use the variable name as the argument.
  • In laissez passer-by-reference with pointer arguments, yous need to use &varName (an address) every bit the argument.

Dynamic Memory Allocation

new and delete Operators

Instead of ascertain an int variable (int number), and assign the address of the variable to the int arrow (int *pNumber = &number), the storage tin exist dynamically allocated at runtime, via a new operator. In C++, whenever you allocate a piece of retentiveness dynamically via new, you need to use delete to remove the storage (i.e., to return the storage to the heap).

The new performance returns a pointer to the memory allocated. The delete operator takes a pointer (pointing to the retentivity allocated via new) as its sole argument.

For instance,

            int number = 88; int * p1 = &number;               int * p2;           cout << p2 << endl;           p2 = new int;                             *p2 = 99; cout << p2 << endl;   cout << *p2 << endl;           delete p2;        

Observe that new and delete operators work on pointer.

To initialize the allocated memory, you can utilise an initializer for fundamental types, or invoke a constructor for an object. For example,

            int * p1 = new int(88); double * p2 = new double(1.23);    int * p1 = new int {88}; double * p2 = new double {i.23};    Appointment * date1 = new Date(1999, 1, 1);   Time * time1 = new Fourth dimension(12, 34, 56);

Yous can dynamically classify storage for global pointers inside a role. Dynamically allocated storage inside the part remains even afterward the office exits. For instance,

one 2 3 4 5 half dozen vii 8 9 10 eleven 12 13 14 15 sixteen 17 18 19 20 21 22
                    #include <iostream> using namespace std;   int * p1, * p2;       void allocate() {    p1 = new int;         *p1 = 88;             p2 = new int(99);  }   int main() {    classify();    cout << *p1 << endl;      cout << *p2 << endl;      delete p1;      delete p2;    render 0; }

The chief differences between static allocation and dynamic allocations are:

  1. In static allocation, the compiler allocates and deallocates the storage automatically, and handle memory management. Whereas in dynamic resource allotment, you lot, as the programmer, handle the memory allocation and deallocation yourself (via new and delete operators). You lot have full control on the pointer addresses and their contents, every bit well as memory management.
  2. Static allocated entities are manipulated through named variables. Dynamic allocated entities are handled through pointers.

new[] and delete[] Operators

Dynamic array is allocated at runtime rather than compile-fourth dimension, via the new[] operator. To remove the storage, you need to employ the delete[] operator (instead of only delete). For example,

1 ii 3 4 5 six 7 8 9 ten 11 12 13 14 15 16 17 18 xix 20 21 22 23 24
                    #include <iostream> #include <cstdlib> using namespace std;   int main() {    const int SIZE = five;    int * pArray;      pArray = new int[SIZE];            for (int i = 0; i < SIZE; ++i) {       *(pArray + i) = rand() % 100;    }        for (int i = 0; i < SIZE; ++i) {       cout << *(pArray + i) << " ";    }    cout << endl;      delete[] pArray;      return 0; }

C++03 does not permit your to initialize the dynamically-allocated array. C++11 does with the brace initialization, equally follows:

            int * p = new int[5] {1, two, three, 4, 5};

Arrow, Array and Office

Array is Treated every bit Pointer

In C/C++, an assortment's proper noun is a pointer, pointing to the offset element (index 0) of the array. For instance, suppose that numbers is an int array, numbers is a also an int arrow, pointing at the first element of the array. That is, numbers is the same every bit &numbers[0]. Consequently, *numbers is number[0]; *(numbers+i) is numbers[i].

For instance,

1 2 3 4 v half-dozen 7 8 ix x 11 12 13 14 fifteen xvi
                    #include <iostream> using namespace std;   int main() {    const int SIZE = 5;    int numbers[SIZE] = {11, 22, 44, 21, 41};                cout << &numbers[0] << endl;     cout << numbers << endl;         cout << *numbers << endl;             cout << *(numbers + ane) << endl;       cout << *(numbers + 4) << endl;    }

Pointer Arithmetic

Equally seen from the previous section, if numbers is an int array, it is treated as an int arrow pointing to the first chemical element of the array. (numbers + 1) points to the next int, instead of having the next sequential accost. Accept notation that an int typically has 4 bytes. That is (numbers + 1) increases the address past four, or sizeof(int). For instance,

int numbers[] = {11, 22, 33}; int * iPtr = numbers; cout << iPtr << endl;         cout << iPtr + 1 << endl;     cout << *iPtr << endl;        cout << *(iPtr + i) << endl;   cout << *iPtr + 1 << endl;        

sizeof Assortment

The operation sizeof(arrayName) returns the total bytes of the array. Yous can derive the length (size) of the array by dividing it with the size of an element (due east.g. chemical element 0). For example,

                    int numbers[100];          cout <<          sizeof(numbers)          << endl;      cout <<          sizeof(numbers[0])          << endl;   cout << "Assortment size is " << sizeof(numbers) / sizeof(numbers[0]) << endl;        

Passing Array In/Out of a Role

An array is passed into a function equally a pointer to the starting time element of the assortment. You can apply array annotation (east.g., int[]) or pointer notation (e.g., int*) in the function declaration. The compiler always treats it every bit arrow (e.1000., int*). For example, the following declarations are equivalent:

int max(int numbers[], int size); int max(int *numbers, int size); int max(int number[50], int size);

They will be treated as int* by the compiler, as follow. The size of the array given in [] is ignored.

int max(int*, int);

Array is passed by reference into the function, because a pointer is passed instead of a clone re-create. If the array is modified inside the part, the modifications are practical to the caller'southward copy. You could declare the array parameter as const to prevent the array from being modified inside the function.

The size of the array is not part of the array parameter, and needs to be passed in another int parameter. Compiler is non able to deduce the array size from the array pointer, and does not perform array bound check.

Instance: Using the usual array annotation.

i 2 3 4 5 half-dozen vii 8 9 10 11 12 xiii fourteen 15 16 17 18 xix xx 21 22 23 24 25 26 27 28 29 xxx 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
                    #include <iostream> using namespace std;    int max(const int arr[], int size); void replaceByMax(int arr[], int size); void print(const int arr[], int size);   int primary() {    const int SIZE = 4;    int numbers[SIZE] = {xi, 22, 33, 22};    print(numbers, SIZE);    cout << max(numbers, SIZE) << endl;    replaceByMax(numbers, SIZE);    print(numbers, SIZE); }     int max(const int arr[], int size) {    int max = arr[0];    for (int i = i; i < size; ++i) {       if (max < arr[i]) max = arr[i];    }    return max; }     void replaceByMax(int arr[], int size) {    int maxValue = max(arr, size);    for (int i = 0; i < size; ++i) {       arr[i] = maxValue;    } }    void impress(const int arr[], int size) {    cout << "{";    for (int i = 0; i < size; ++i) {       cout << arr[i];       if (i < size - 1) cout << ",";    }    cout << "}" << endl; }

Take notation that you lot can modify the contents of the caller's assortment inside the function, as array is passed by reference. To prevent accidental modification, you could employ const qualifier to the role's parameter. Recall that const inform the compiler that the value should not be changed. For instance, suppose that the function print() prints the contents of the given array and does not modify the array, you could apply const to both the assortment name and its size, as they are not expected to be changed inside the function.

void print(const          int arr[],          int          size);

Compiler flags out an error "assignment of read-only location" if it detected a const value would be inverse.

Example: Using pointer notation.

1 ii 3 4 five vi vii 8 9 x xi 12 thirteen 14 fifteen sixteen 17 18 19 20 21
                    #include <iostream> using namespace std;    int max(const int *arr, int size);   int main() {    const int SIZE = v;    int numbers[SIZE] = {10, twenty, 90, 76, 22};    cout << max(numbers, SIZE) << endl; }    int max(const int *arr, int size) {    int max =                  *arr;    for (int i = 1; i < size; ++i) {       if (max <                  *(arr+i)) max =                  *(arr+i);    }    render max; }

Pass-by-Reference and sizeof

1 2 3 4 5 vi 7 8 9 10 11 12 xiii 14 fifteen 16 17 18 19 xx 21
                    #include <iostream> using namespace std;    void fun(const int *arr, int size);    int primary() {    const int SIZE = v;    int a[SIZE] = {8, 4, 5, 3, 2};    cout << "sizeof in main() is " <<                  sizeof(a)                  << endl;    cout << "address in main() is " << a << endl;    fun(a, SIZE); }    void fun(const int *arr, int size) {    cout << "sizeof in function is " <<                  sizeof(arr)                  << endl;    cout << "address in part is " << arr << endl; }
sizeof in principal() is 20 address in master() is 0x22fefc sizeof in part is 4 address in function is 0x22fefc

The address of arrays in main() and the function are the same, as expected, equally array is passed past reference.

In main(), the sizeof array is xx (four bytes per int, length of v). Inside the function, the sizeof is 4, which is the sizeof int pointer (iv-byte address). This is why yous need to laissez passer the size into the part.

Operating on a Range of an Array

one 2 3 iv v 6 7 8 9 x 11 12 thirteen 14 15 16 17 eighteen 19 20 21 22 23 24 25
                    #include <iostream> using namespace std;    int sum(const int *begin, const int *cease);    int master() {    int a[] = {eight, four, five, iii, 2, 1, 4, 8};    cout << sum(a, a+8) << endl;           cout << sum(a+2, a+v) << endl;         cout << sum(&a[two], &a[5]) << endl;  }      int sum(const int *begin, const int *end) {    int sum = 0;    for (const int *p = begin; p != terminate; ++p) {       sum += *p;    }    return sum; }

Program Notes:

  • To write a office that operates on a range of the given array, you can pass the brainstorm pointer and the end pointer into the office. Past convention, the operation shall start at the brainstorm arrow, upwards to the stop arrow, but excluding the stop pointer.
  • In "const int *p", *p (content pointed-to) is constant, merely p is not constant.

C-String and Pointer

C-cord (of the C language) is a character array, terminated with a null grapheme '\0'. For example,

1 2 3 four v 6 7 8 9 10 xi 12 13 14 15 16 17 18 xix xx 21 22 23 24 25 26 27
                    #include <iostream> #include <cstring> using namespace std;   int primary() {    char msg1[] = "How-do-you-do";    char *msg2 = "Hi";            cout << strlen(msg1) << endl;       cout << strlen(msg2) << endl;    cout << strlen("Hello") << endl;      int size = sizeof(msg1)/sizeof(char);    cout << size << endl;     for (int i = 0; msg1[i] != '\0'; ++i) {       cout << msg1[i];    }    cout << endl;      for (char *p = msg1; *p != '\0'; ++p) {                 cout << *p;    }    cout << endl; }

Take note that for C-String part such as strlen() (in header cstring, ported over from C'southward string.h), in that location is no demand to pass the array length into the part. This is because C-Strings are terminated past '\0'. The office can iterate thru the characters in the assortment until '\0'. For instance,

i 2 3 4 5 6 7 8 9 10 xi 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
                    #include <iostream> #include <cstring> using namespace std;   int count(const char *str, const char c);     int main() {    char msg1[] = "Hello, globe";    char *msg2 = "Hello, world";      cout << count(msg1, '50') << endl;    cout << count(msg2, 'fifty') << endl;    cout << count("Hello, earth", 'l') << endl; }     int count(const char *str, const char c) {    int count = 0;    while (*str) {          if (*str == c) ++count;       ++str;    }    return count; }

*More On Pointers

Function Pointer

In C/C++, functions, similar all information items, have an accost. The name of a role is the starting address where the function resides in the memory, and therefore, tin can be treated every bit a pointer. We can pass a function arrow into function every bit well. The syntax for declaring a function arrow is:

            render-type          (*          function-ptr-proper noun) (parameter-listing)    double (*fp)(int, int)   double *dp;              double *fun(int, int)     double f(int, int);       fp = f;        
Example
one 2 3 4 5 6 7 8 9 10 11 12 xiii 14 15 16 17 18 19 20 21 22 23 24 25
                    #include <iostream> using namespace std;   int arithmetic(int, int,                  int (*)(int, int));       int add(int, int); int sub(int, int);   int add(int n1, int n2) { return n1 + n2; } int sub(int n1, int n2) { return n1 - n2; }   int arithmetic(int n1, int n2,                  int (*functioning) (int, int)) {    return                  (*operation)(n1, n2); }   int main() {    int number1 = v, number2 = 6;          cout << arithmetics(number1, number2, add) << endl;        cout << arithmetic(number1, number2, sub) << endl; }

Generic Pointer or void Pointer (void *)

A void pointer can hold accost of any data type (except role arrow). We cannot operate on the object pointed to by void pointer, as the type is unknown. We can apply a void pointer to compare with another accost.

[TODO] Example

Constant Arrow vs. Constant Pointed-to Data

  1. Non-constant pointer to constant data: Data pointed to CANNOT exist inverse; just pointer CAN be changed to indicate to some other data. For example,
    int i1 = 8, i2 = 9;              const              int * iptr = &i1;   // *iptr = 9;              // error: consignment of read-but location              iptr = &i2;            
  2. Constant pointer to non-constant data: Information pointed to Tin can be changed; but pointer CANNOT be changed to betoken to another data. For example,
    int i1 = 8, i2 = 9; int *              const              iptr = &i1;   *iptr = ix;    // iptr = &i2;              // mistake: consignment of read-only variable            
  3. Abiding arrow to constant data: Data pointed to CANNOT be inverse; and pointer CANNOT exist changed to signal to another data. For example,
    int i1 = eight, i2 = nine;              const              int *              const              iptr = &i1;   // *iptr = nine;              // fault: assignment of read-only variable              // iptr = &i2;              // mistake: assignment of read-just variable            
  4. Not-abiding pointer to non-abiding data: Data pointed to Can be changed; and pointer Tin exist inverse to indicate to another data. For example,
    int i1 = eight, i2 = 9; int *              iptr = &i1;   *iptr = 9;    iptr = &i2;            

Link to "C++ References & Resource"

cushmandombef.blogspot.com

Source: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp4_PointerReference.html

0 Response to "what happens to initialize pointers at end of function c++"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel