Skip to content

Commit 4d3200c

Browse files
author
mikeblome
committed
more code
1 parent 412771e commit 4d3200c

1 file changed

Lines changed: 64 additions & 185 deletions

File tree

docs/cpp/pointers-cpp.md

Lines changed: 64 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,18 @@ ms.assetid: 595387c5-8e58-4670-848f-344c7caf985e
66
---
77
# Pointers (C++)
88

9-
A pointer stores the address of a object in memory and is used to access that object. On 64-bit operating systems a pointer has a size of 64 bits; a system's pointer size determines how much addressable memory it can have. A pointer can point to a typed object or to **void**. A non-const pointer can be incremented or decremented, which causes it to point to a new location in memory. This is called *pointer arithmetic* and is used in C-style programming to iterate over elements in arrays or other data structures. A const pointer cannot be made to point to a different memory location, and in that sense is very similar to a [reference](references-cpp.md).
9+
A pointer stores the address of a object in memory and is used to access that object. On 64-bit operating systems a pointer has a size of 64 bits; a system's pointer size determines how much addressable memory it can have. A pointer can point to a typed object or to **void**. When a program allocates a new object on the [heap]() in memory, it receives the address of that object in the form of a pointer. Such pointers are called *owning pointers*; an owning pointer (or a copy of it) must be used to explicitly delete the heap-allocated object when it is no longer needed. Failure to delete the memory results in a *memory leak* and renders the memory unavailable to any other program on the machine.
1010

11-
Pointers are used extensively in C++ to pass larger objects to and from functions because it is far more efficient to copy a 64-bit value than to copy an entire object. When a program allocates a new object on the [heap]() in memory, it receives the address of that object in the form of a pointer. Such pointers are called *owning pointers* because they must be used to explicitly delete the object when it is no longer needed. Pointers to functions enable functions to be passed to other functions and are used for "callbacks" in C-style programming.
11+
A pointer (if it is not declared as **const**) can be incremented or decremented so that it points to a new location in memory. This is called *pointer arithmetic* and is used in C-style programming to iterate over elements in arrays or other data structures. A **const** pointer cannot be made to point to a different memory location, and in that sense is very similar to a [reference](references-cpp.md).
1212

13-
deferencing
13+
Pointers (along with references) are used extensively in C++ to pass larger objects to and from functions because it is usually far more efficient to copy a pointer than to copy an entire object. When defining a function, specify pointer parameters as **const** unless you intend for the function to modify the object. In general, **const** references are the preferred way to pass objects to functions unless the value of the object can possibly be **nullptr**.
1414

15-
char* p ="Hello";
15+
Pointers to functions enable functions to be passed to other functions and are used for "callbacks" in C-style programming.
1616

17-
print p vs. *p
17+
## Pointer errors
1818

1919
In C and C++, pointer errors are by far the greatest cause of crashes, hangs, data corruption, security holes and general programmer misery. In modern C++, the use of *raw pointers* is strongly discouraged except in very specific scenarios. Modern C++ provides *smart pointers* for allocating objects, *iterators* for traversing data structures, and *lambda expressions* for passing callable functions. By using these language and library facilities instead of raw pointers, you will make your program safer, easier to debug, and simpler to understand and maintain.
2020

21-
## Syntax
22-
23-
```cpp
24-
MyClass* p;
25-
26-
```
27-
2821
## Initialization and member access
2922

3023
The following example shows how to declare a pointer and initialize it with an object allocated on the heap, and then how to use it. It also shows a few of the dangers associated with pointers.
@@ -69,36 +62,43 @@ int main()
6962
{
7063
// Use the * operator to declare a pointer type
7164
// Use new to allocate and initialize memory
72-
MyClass* mc = new MyClass{ 108, "Mike" };
65+
MyClass* pmc = new MyClass{ 108, "Mike" };
7366

7467
// Prints the memory address. Usually not what you want.
75-
// std:: cout << mc << std::endl;
68+
std:: cout << pmc << std::endl;
69+
70+
// Copy the pointed-to object by dereferencing the pointer
71+
// to access the contents of the memory location.
72+
// mc is a separate object, allocated here on the stack
73+
MyClass mc = *pmc;
74+
75+
// Declare a pointer that points to mc using the addressof operator
76+
MyClass* pcopy = &mc;
7677

7778
// Use the -> operator to access the object's public members
78-
mc->print(); // "Mike, 108"
79+
pmc->print(); // "Mike, 108"
7980

80-
// Copy the pointer. Now mc and mc2 point to same object!
81-
MyClass* mc2 = mc;
81+
// Copy the pointer. Now pmc and pmc2 point to same object!
82+
MyClass* pmc2 = pmc;
8283

8384
// Use copied pointer to modify the original object
84-
mc2->name = "Lisa";
85-
mc->print(); // "Lisa, 108"
86-
mc2->print(); // "Lisa, 108"
85+
pmc2->name = "Lisa";
86+
pmc->print(); // "Lisa, 108"
87+
pmc2->print(); // "Lisa, 108"
8788

8889
// Pass the pointer to a function.
8990
func_A(mc);
90-
mc->print(); // "Lisa, 3"
91-
mc2->print(); // "Lisa, 3"
91+
pmc->print(); // "Lisa, 3"
92+
pmc2->print(); // "Lisa, 3"
9293

9394
// Dereference the pointer and pass a copy
9495
// of the pointed-to object to a function
9596
func_B(*mc);
96-
mc->print(); // "Lisa, 3" (original not modified by function)
97+
pmc->print(); // "Lisa, 3" (original not modified by function)
9798

98-
delete(mc); // don't forget to give memory back to operating system!
99-
// delete(mc2); //crash! memory location was already deleted
99+
delete(pmc); // don't forget to give memory back to operating system!
100+
// delete(pmc2); //crash! memory location was already deleted
100101
}
101-
102102
```
103103
104104
## Const pointers and pointers to const objects
@@ -110,19 +110,48 @@ A const pointer can point to either a const or non-const object, but can't be mo
110110
Certain arithmetic operations can be performed on non-const pointers to make them point to a new memory location. A pointer can be incremented and decremented using the **++**, **+=**, **-=** and **--** operators. This technique can be used in arrays and is especially useful in buffers of untyped data. A **void\*** increments by the size of a **char** (1 byte). A typed pointer increments by size of the type it points to.
111111
112112
```cpp
113-
// pointers.cpp : This file contains the 'main' function. Program execution begins and ends there.
114-
//
113+
#include <iostream>
114+
#include <string>
115+
116+
using namespace std;
115117
118+
119+
class MyClass
120+
{
121+
public:
122+
int num;
123+
std::string name;
124+
void print() { std::cout << name << ":" << num << std::endl; }
125+
};
126+
127+
128+
int main()
129+
{
116130
// Pointer arithmetic may be done with an array declared
117131
// on the stack or allocated on the heap with new.
118132
// The increment operator takes into account the size
119-
// of the objects pointed to.
120-
p = new int[5];
121-
for (i = 0; i < 5; i++, p++) {
122-
*p = i * 10;
123-
printf_s("0x%p %d\n", p, *p);
133+
// of the objects pointed to. In this example p increments by sizeof(int)
134+
int* p = new int[5];
135+
for (i = 0; i < 5; i++, p++)
136+
{
137+
*p = i * 10; // set the value of the pointed-to int
138+
printf_s("0x%p %d\n", p, *p); //print the pointer address, and the value of the pointed-to int
124139
}
125140
141+
MyClass arr[3];
142+
arr[0] = {108, "Mike"};
143+
arr[1] = {109, "Lisa"};
144+
arr[2] = {110, "Tabby"};
145+
146+
// pmc increments by sizeof(MyClass):
147+
148+
MyClass* pmc = &arr[0];
149+
cout << pmc->name; // Mike
150+
pmc++;
151+
cout << pmc->name; // Lisa
152+
pmc++;
153+
cout << pmc->name; //Tabby
154+
126155
// A common expression seen is dereferencing in combination
127156
// with increment or decrement operators, as shown here.
128157
// The indirection operator * takes precedence over the
@@ -138,35 +167,7 @@ Certain arithmetic operations can be performed on non-const pointers to make the
138167
139168
// s2 was copied into s1, so now they are both equal to "dog"
140169
printf_s("%s %s", s1, s2);
141-
142-
#include <iostream>
143-
#include <string>
144-
145-
using namespace std;
146-
147-
class MyClass
148-
{
149-
public:
150-
int num;
151-
std::string name;
152-
void print() { std::cout << name << ":" << num << std::endl; }
153-
};
154-
155-
int main()
156-
{
157-
MyClass arr[3];
158-
arr[0] = {108, "Mike"};
159-
arr[1] = {109, "Lisa"};
160-
arr[2] = {110, "Tabby"};
161-
162-
MyClass* pmc = &arr[0];
163-
cout << pmc->name;
164-
pmc++;
165-
cout << pmc->name;
166-
pmc++;
167-
cout << pmc->name;
168170
}
169-
170171
```
171172

172173
## void* pointers
@@ -176,33 +177,6 @@ A pointer to **void** simply points to a raw memory location. Sometimes it is un
176177
## Pointers to functions
177178

178179
TBD
179-
180-
> \[*storage-class-specifiers*] \[*cv-qualifiers*] *type-specifiers* \[*ms-modifier*] *declarator* **;**
181-
182-
where any valid pointer declarator may be used for *declarator*. The syntax for a simple pointer declarator is as follows:
183-
184-
> __\*__ \[*cv-qualifiers*] *identifier* \[**=** *expression*]
185-
186-
1. The declaration specifiers:
187-
188-
- An optional storage class specifier. For more information, see [Specifiers](../cpp/specifiers.md).
189-
190-
- An optional **const** or **volatile** keyword applying to the type of the object to be pointed to.
191-
192-
- The type specifier: the name of a type representing the type of the object to be pointed to.
193-
194-
1. The declarator:
195-
196-
- An optional Microsoft-specific modifier. For more information, see [Microsoft-Specific Modifiers](../cpp/microsoft-specific-modifiers.md).
197-
198-
- The __\*__ operator.
199-
200-
- An optional **const** or **volatile** keyword applying to the pointer itself.
201-
202-
- The identifier.
203-
204-
- An optional initializer.
205-
206180
The declarator for a pointer to function looks like this:
207181

208182
> __(\*__ \[*cv-qualifiers*] *identifier* **)(** *argument-list* **)** \[*cv-qualifers*] \[*exception-specification*] \[**=** *expression*] **;**
@@ -211,97 +185,6 @@ For an array of pointers, the syntax looks like this:
211185

212186
> __\*__ *identifier* **\[** \[*constant-expression*] **]**
213187
214-
Multiple declarators and their initializers may appear together in a single declaration in a comma separated list following the declaration specifier.
215-
216-
A simple example of a pointer declaration is:
217-
218-
```cpp
219-
char *pch;
220-
```
221-
222-
The preceding declaration specifies that `pch` points to an object of type **char**.
223-
224-
A more complex example is
225-
226-
```cpp
227-
static unsigned int * const ptr;
228-
```
229-
230-
The preceding declaration specifies that `ptr` is a constant pointer to an object of type **unsigned** **int** with static storage duration.
231-
232-
The next example shows how multiple pointers are declared and initialized:
233-
234-
```cpp
235-
static int *p = &i, *q = &j;
236-
```
237-
238-
In the preceding example, pointers p and q both point to objects of type **int** and are initialized to the addresses of i and j respectively. The storage class specifier **static** applies to both pointers.
239-
240-
## Example
241-
242-
```cpp
243-
// pointer.cpp
244-
// compile with: /EHsc
245-
#include <iostream>
246-
int main() {
247-
int i = 1, j = 2; // local variables on the stack
248-
int *p;
249-
250-
// a pointer may be assigned to "point to" the value of
251-
// another variable using the & (address of) operator
252-
p = &j;
253-
254-
// since j was on the stack, this address will be somewhere
255-
// on the stack. Pointers are printed in hex format using
256-
// %p and conventionally marked with 0x.
257-
printf_s("0x%p\n", p);
258-
259-
// The * (indirection operator) can be read as "the value
260-
// pointed to by".
261-
// Since p is pointing to j, this should print "2"
262-
printf_s("0x%p %d\n", p, *p);
263-
264-
// changing j will change the result of the indirection
265-
// operator on p.
266-
j = 7;
267-
printf_s("0x%p %d\n", p, *p );
268-
269-
// The value of j can also be changed through the pointer
270-
// by making an assignment to the dereferenced pointer
271-
*p = 10;
272-
printf_s("j is %d\n", j); // j is now 10
273-
274-
// allocate memory on the heap for an integer,
275-
// initialize to 5
276-
p = new int(5);
277-
278-
// print the pointer and the object pointed to
279-
// the address will be somewhere on the heap
280-
printf_s("0x%p %d\n", p, *p);
281-
282-
// free the memory pointed to by p
283-
delete p;
284-
285-
// At this point, dereferencing p with *p would trigger
286-
// a runtime access violation.
287-
288-
289-
}
290-
```
291-
292-
```Output
293-
0x0012FEC8
294-
0x0012FEC8 2
295-
0x0012FEC8 7
296-
j is 10
297-
0x00320850 5
298-
0x00320850 0
299-
0x00320854 10
300-
0x00320858 20
301-
0x0032085C 30
302-
0x00320860 40
303-
dog dog
304-
```
305188

306189
## Example
307190

@@ -386,9 +269,9 @@ a (add node) d (display list) q (quit)
386269

387270
## Example
388271

272+
The following example demonstrates how pointer arithmetic can be used to access individual pixels in a bitmap. Note the use of **new** and **delete**, and the dereference operator.
273+
389274
```cpp
390-
// pointer_arithmetic.cpp : This file contains the 'main' function. Program execution begins and ends there.
391-
//
392275

393276
#include <iostream>
394277
#include <string>
@@ -419,15 +302,13 @@ int main()
419302
bf.bfReserved2 = 0;
420303
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //54
421304

422-
423305
// Create a gray square with a 2-pixel wide outline
424306
unsigned char* begin = &buffer[0];
425307
unsigned char* end = &buffer[0] + bufferSize;
426308
unsigned char* p = begin;
427309
constexpr int pixelWidth = 3;
428310
constexpr int borderWidth = 2;
429311

430-
int c = 0;
431312
while (p < end)
432313
{
433314
// is top or bottom row:
@@ -444,10 +325,8 @@ int main()
444325
*p = 0xC3;
445326
}
446327
p++; //increment one byte (char)
447-
c++;
448328
}
449329

450-
cout << "c = " << c;
451330
ofstream wf(R"(box.bmp)", ios::out | ios::binary);
452331

453332
wf.write(reinterpret_cast<char*>(&bf), sizeof(bf));

0 commit comments

Comments
 (0)