Unit 2: Handling Pointers, Arrays and String
I. Orientation — Memory, Addresses, Collections, and Text
C++ provides low-level memory access through pointers, structured data collections through arrays, and safe text processing through std::string. These mechanisms differ in abstraction but depend on correct object lifetime, type compatibility, bounds management, and ownership.
- Object and address: An object occupies storage, has a type, and usually has an address obtainable with
&; forint x = 5;,&xis the address ofx. - Indirection: The unary
*operator accesses the object at a valid pointer’s stored address; ifint* p = &x;, then*pdenotesx. - Lifetime rule: A pointer or reference may be used only while its target object remains alive.
- Array convention: Array elements occupy contiguous memory and use zero-based indexing; an array of size
nhas valid indices0throughn - 1. - String convention:
std::stringmanages a dynamic character sequence and should normally be preferred to manually managed C-style character arrays. - Safety conditions: Dereferencing null, wild, or dangling pointers and accessing outside array bounds cause undefined behavior.
II. Pointer Fundamentals — Address-Based Access
Pointers store memory addresses and permit indirect access, traversal, dynamic allocation, and interaction with generic memory.
A. Pointer vs reference variables
A pointer stores an address and can be redirected, whereas a reference is an alias that must be initialized when declared.
- Declaration:
int* pdeclares a pointer toint;int& rdeclares a reference toint. - Initialization: A pointer may hold
nullptr, but a reference must bind to an existing object. - Access: A pointer requires
*pfor the target value; a reference is used like the original variable. - Reassignment: Assigning another address redirects a pointer, while assigning through a reference changes its bound object.
- Comparison:
- Pointer: Supports arithmetic, null state, and redirection.
- Reference: Offers simpler syntax and is commonly used for non-null function parameters.
int x = 10, y = 20;
int* p = &x; // p stores x's address
int& r = x; // r aliases x
p = &y; // p now points to y
r = y; // assigns 20 to x; r still aliases xB. Void pointer
A void pointer, written void*, can hold the address of any object type but cannot be dereferenced directly.
- Generic storage: Converting
int*ordouble*tovoid*preserves the address but hides the pointed-to type. - Required conversion: The pointer must be converted back to the correct type before dereferencing.
- Restriction: Standard C++ does not permit arithmetic on
void*because the pointed-to element size is unknown. - Risk: Converting to the wrong type and dereferencing can produce undefined behavior.
int value = 25;
void* vp = &value;
int* ip = static_cast<int*>(vp);
int result = *ip; // result is 25C. Pointer arithmetic
Pointer arithmetic moves in units of the pointed-to type and is valid only within an array or one position beyond it.
- Increment: If
ppoints toa[0], thenp + 1points toa[1], advancing bysizeof(int)bytes for anint*. - Subtraction: For pointers into the same array,
q - pgives the number of elements between them. - Index equivalence:
p[i]is defined as*(p + i). - Boundary: A one-past-the-end pointer may be formed and compared, but it must not be dereferenced.
int a[3] = {10, 20, 30};
int* p = a;
int second = *(p + 1); // 20Here, a is the array, p points to its first element, and second stores the next element.
D. Pointer to pointer
A pointer to pointer stores the address of another pointer and introduces two levels of indirection.
- Declaration:
int** ppmeans thatpppoints to anint*. - Dereferencing:
*ppyields the inner pointer, while**ppyields the final integer. - Use cases: It supports modification of a caller’s pointer and representation of dynamically allocated tables.
- Type consistency: Each
*removes exactly one pointer level.
int x = 7;
int* p = &x;
int** pp = &p;
**pp = 9; // changes x to 9E. Dangling pointer
A dangling pointer retains an address after the target object’s lifetime has ended.
- Deletion case: After
delete p, the allocated object no longer exists, even thoughpmay still contain its former address. - Scope case: Returning the address of a local automatic variable creates a dangling pointer when the function ends.
- Consequence: Dereferencing a dangling pointer causes undefined behavior.
- Prevention: Reset non-owning remnants to
nullptrand prefer RAII facilities such asstd::unique_ptr.
int* p = new int(5);
delete p;
p = nullptr; // prevents accidental use of the old addressF. Wild pointer
A wild pointer is an uninitialized pointer whose stored bit pattern does not intentionally identify a valid object.
- Cause:
int* p;creates an uninitialized local pointer when no initializer is supplied. - Danger: Reading or dereferencing its indeterminate value causes undefined behavior.
- Prevention: Initialize immediately with a valid address or
nullptr. - Distinction: A wild pointer was never properly initialized; a dangling pointer once referred to a live object.
int* p = nullptr; // defined null state, not a wild pointerG. Null pointer assignment
Null pointer assignment explicitly records that a pointer currently points to no object.
- Modern literal:
nullptr, introduced in C++11, has typestd::nullptr_tand converts safely to pointer types. - Testing:
if (p != nullptr)or simplyif (p)checks whether a pointer is non-null. - Dereferencing rule:
*pandp->memberare invalid whenpis null. - Preference: Use
nullptrrather than0orNULLbecause it avoids integer-overload ambiguity.
int* p = nullptr;
if (p) {
int value = *p;
}III. Pointers and Classes — Object-Oriented Indirection
Pointers participate in object state, object access, member selection, and communication between an object and its member functions.
A. Pointers as class members
A pointer data member stores an address as part of each object and may represent ownership or a non-owning relationship.
- Initialization: Pointer members should be initialized in a constructor’s member-initializer list.
- Ownership: A raw owning pointer requires correct destruction, copying, and assignment—the Rule of Three or Rule of Five.
- Shallow-copy danger: Default copying duplicates only the address, potentially causing shared mutation or double deletion.
- Preferred design: Use
std::unique_ptr<T>for exclusive ownership and ordinary pointers for clearly documented non-owning links.
class Box {
int* value;
public:
explicit Box(int v) : value(new int(v)) {}
~Box() { delete value; }
Box(const Box&) = delete;
Box& operator=(const Box&) = delete;
};Here, value owns one dynamically allocated int, and copying is prohibited.
B. Pointer to objects
A pointer to an object stores the object’s address and accesses members through the arrow operator.
- Syntax: If
Student* ppoints to aStudent, thenp->show()is equivalent to(*p).show(). - Automatic object:
Student s; Student* p = &s;does not requiredelete. - Dynamic object: An object created by
new Studentmust be released bydelete, unless managed by a smart pointer. - Polymorphism: A base-class pointer can refer to a derived object; virtual functions then enable runtime dispatch.
class Item {
public:
int price = 50;
};
Item object;
Item* p = &object;
int cost = p->price; // 50C. This pointer
The this pointer is an implicit pointer to the object for which a non-static member function was invoked.
- Type: In a member of class
C,thisbehaves asC* const; in aconstmember, it behaves asconst C* const. - Disambiguation:
this->value = value;distinguishes a data member from a parameter with the same name. - Chaining: Returning
*thisby reference enables expressions such asa.set(1).set(2). - Restriction: Static member functions have no
thispointer because they are not called for a particular object.
class Number {
int value;
public:
Number& set(int value) {
this->value = value;
return *this;
}
};D. Pointer to data member
A pointer to data member identifies a member within a class rather than storing a complete ordinary memory address.
- Declaration:
int Record::* pm = &Record::score;declarespmas a pointer to anintmember ofRecord. - Object access: Use
object.*pmwith an object. - Pointer access: Use
pointer->*pmwith a pointer to an object. - Purpose: It allows member selection to be passed as data while preserving class type information.
struct Record { int score; };
int Record::* pm = &Record::score;
Record r{80};
Record* pr = &r;
int a = r.*pm; // 80
int b = pr->*pm; // 80IV. Arrays — Fixed-Size Contiguous Collections
An array stores a fixed number of same-type elements contiguously, permitting indexed processing and predictable memory layout.
A. Array declaration and processing of multidimensional arrays inside main and inside class
A multidimensional array is an array whose elements are themselves arrays, commonly used to represent matrices.
- Inside
main:int m[2][3]defines two rows and three columns, giving six integers. - Initialization:
int m[2][3] = {{1,2,3},{4,5,6}};initializes rows explicitly. - Processing: Nested loops use
m[i][j], whereiis the row index andjis the column index. - Inside a class: A built-in array can be a private data member and processed through member functions.
- Storage order: C++ stores multidimensional built-in arrays in row-major order.
class Matrix {
int data[2][3]{};
public:
void setAll(int value) {
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 3; ++j)
data[i][j] = value;
}
};Here, data is the matrix, i selects a row, j selects a column, and value is assigned to every element.
B. Array of objects
An array of objects contains multiple class instances, with each element constructed and accessed independently.
- Declaration:
Student group[3];creates threeStudentobjects using the default constructor. - Initialization:
Point points[2]{{1,2}, {3,4}};initializes two objects when matching constructors exist. - Access:
group[i].show()selects elementiand calls its member function. - Lifetime: Constructors run from the first element to the last; destructors run in reverse order.
- Dynamic alternative:
std::vector<T>is preferable when the number of objects is determined at runtime.
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
};
Point points[2] = {{1, 2}, {3, 4}};V. C++ Strings — Managed Character Sequences
The standard string abstraction manages storage automatically and supplies operations for construction, assignment, searching, comparison, and modification.
A. Standard C++ string class
The std::string class represents a mutable sequence of char values and is declared in the <string> header.
- Namespace: Its full name is
std::string. - Size management: Storage expands or contracts automatically;
size()andlength()return the character count. - Indexing:
s[i]performs unchecked access, whiles.at(i)checks bounds and may throwstd::out_of_range. - Comparison: Operators such as
==,<, and>compare string contents lexicographically. - Input:
std::cin >> sreads one whitespace-delimited word;std::getline(std::cin, s)reads a full line.
#include <string>
std::string text = "C++";
std::size_t n = text.size(); // n is 3B. Defining and assigning string objects
String objects can be default-constructed, initialized from literals or other strings, and reassigned after creation.
- Empty definition:
std::string s;creates an empty string. - Direct initialization:
std::string s("Object");copies characters from a string literal. - Copy initialization:
std::string b = a;createsbwith the same contents asa. - Assignment:
s = "Pointer";replaces the previous contents. - Concatenation:
a + bcreates a combined string, whilea += bappends toa.
std::string first = "Object";
std::string second;
second = first;
second += " Oriented"; // "Object Oriented"C. Modifiers of string class
String modifiers change a string’s contents, length, or arrangement while maintaining managed storage.
append()and+=: Add characters at the end, as ins.append("++").push_back()andpop_back(): Add or remove one final character;pop_back()requires a non-empty string.insert(): Places content at a specified index, as ins.insert(1, "X").erase(): Removes characters;s.erase(pos, count)starts atposand removes at mostcountcharacters.replace(): Replaces a selected range with new text.clear()andresize():clear()makes the string empty, whileresize(n, ch)changes its length and may fill new positions withch.- Iterator modifiers: Overloads of
insert()anderase()can operate at iterator positions, supporting algorithm-oriented code.
std::string s = "cat";
s.append("alog"); // "catalog"
s.insert(3, ""); // remains "catalog"
s.replace(0, 3, "dia"); // "dialog"
s.erase(3, 2); // "diag"Here, numeric arguments are zero-based positions and character counts; modifiers may invalidate pointers, references, and iterators into the string when storage is reallocated.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →