0% found this document useful (0 votes)
6 views15 pages

CPP Programming Basics Study Notes

The document provides an overview of C++ programming basics, covering topics such as input/output, data types, structures, and memory management. It highlights the advantages of learning C++, its history, and the key differences between C and C++. Additionally, it includes practical examples and explanations of fundamental concepts like namespaces, string handling, and reference variables.

Uploaded by

Shahriar Hossain
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views15 pages

CPP Programming Basics Study Notes

The document provides an overview of C++ programming basics, covering topics such as input/output, data types, structures, and memory management. It highlights the advantages of learning C++, its history, and the key differences between C and C++. Additionally, it includes practical examples and explanations of fundamental concepts like namespaces, string handling, and reference variables.

Uploaded by

Shahriar Hossain
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

C++ Programming Basics

Study Notes

SC1008 C and C++ Programming

Week 8 Lecture

Course Instructor: Assistant Professor WANG Yong

yong-wang@[Link]

Nanyang Technological University

School of Computer Science and Engineering


Table of Contents

1. Introduction to C++ Why learn C++, History, C vs C++

2. Input/Output cout, cin, Namespaces, String handling

3. Data Types Basic types, Compound types, sizeof operator

4. Structures and Unions Differences from C, Memory efficiency

5. String Class C++ string methods and operations

6. Reference Variables Aliases, Reference vs Pointer

7. Dynamic Memory Allocation new and delete operators

8. Functions Inline, Default arguments, Overloading, Templates


1. Introduction to C++
1.1 Why Learn C++?
C++ is one of the most popular and widely-used programming languages in the world. According to the
TIOBE index, C++ consistently ranks among the top programming languages. Learning C++ offers
numerous advantages for software developers and computer science students alike.

• Popularity and High Salary: C++ developers are in high demand and often command competitive
salaries in the job market.
• Abundant Library Support: The C++ ecosystem includes a vast collection of libraries for various
applications including graphics, networking, and scientific computing.
• Large Community: A massive global community means extensive documentation, tutorials, forums,
and third-party resources are readily available.
• Portability: C++ code can be compiled and run on virtually any platform with minimal
modifications.
• Wide Usage: C++ is extensively used in database systems, operating systems, game development,
graphics engines, embedded systems, and high-performance applications.

1.2 History of C++


C++ was developed by Bjarne Stroustrup, a Danish computer scientist at Bell Telephone Laboratories
(now Nokia Bell Labs) in New Jersey, USA. The development began in 1979 as an extension to the C
language.

• 1979: Bjarne Stroustrup began work on 'C with Classes' to bring object-oriented programming
features from Simula into C.
• Simula Influence: Simula was the first language to support object-oriented programming but was too
slow for practical use.
• 1983: The language was renamed from 'C with Classes' to C++. The '++' operator represents
increment, symbolizing that C++ is an evolution of C.
• Major Updates: The language has undergone significant updates in 2011 (C++11), 2014 (C++14),
2017 (C++17), and continues to evolve with C++20 and beyond.

1.3 C vs C++
Understanding the relationship between C and C++ is fundamental to mastering both languages. C++ is
designed as a superset of C, meaning that virtually any valid C program is also a valid C++ program.
However, C++ extends C with powerful new features and paradigms.

C++ joins three separate programming paradigms into one unified language:

• Procedural Programming: Inherited from C, supporting structured programming with functions and
modular code organization.
• Object-Oriented Programming (OOP): Added through class enhancements, supporting
encapsulation, inheritance, and polymorphism.
• Generic Programming: Supported through C++ templates, enabling code that works with multiple
data types without duplication.

2. Input/Output
2.1 Your First C++ Program
Every C++ program must have a main() function as its entry point. C++ program files typically use the
extension '.cpp', though '.cc' and '.cxx' are also valid. Here is the classic 'Hello World' program that
demonstrates the fundamental structure of C++ programs:

//[Link]
#include <iostream> // Header file for input/output stream
using namespace std; // Use the standard namespace

int main() {
cout << "Hello world!" << endl; // Output text to console
cout << "I'm from NTU.\n"; // \n also creates new line
return 0;
}

Key Components: The '#include' directive imports the iostream library which contains definitions for
input/output operations. The 'using namespace std' statement allows us to use cout and endl without the
'std::' prefix. The 'cout' object (console output) uses the insertion operator '<<' to send data to the console.
The 'endl' manipulator inserts a newline character and flushes the output buffer.

2.2 Namespaces
Namespaces are a feature introduced in C++ to avoid name conflicts when using multiple libraries.
Consider a scenario where two libraries both define classes named 'List' or 'Tree'. Without namespaces, the
compiler cannot distinguish between them. Namespaces solve this by providing a scope context for
identifiers.

// Defining namespaces in a header file


namespace English {
void greet() { std::cout << "Hello!" << std::endl; }
}

namespace Spanish {
void greet() { std::cout << "Hola!" << std::endl; }
}

When using functions from different namespaces with the same name, you can specify which version to
call using the scope resolution operator '::'. For example, 'English::greet()' calls the English version, while
'Spanish::greet()' calls the Spanish version. The 'using namespace std' directive allows direct access to all
entities in the standard namespace without the 'std::' prefix.

2.3 Output with cout


The cout object can output multiple data types seamlessly. C++ automatically handles type conversion for
output, making it much more convenient than C's printf() function which requires format specifiers.

int age = 25;


float pi = 3.14159;
double largeNum = 1234567.89;
char grade = 'A';
bool isStudent = true;

cout << "Age: " << age << endl;


cout << "Pi: " << pi << endl;
cout << "Grade: " << grade << endl;
cout << "Student: " << boolalpha << isStudent << endl;
cout << fixed << setprecision(2) << largeNum << endl;

The 'boolalpha' manipulator displays boolean values as 'true' or 'false' instead of 1 and 0. The 'fixed' and
'setprecision(n)' manipulators control floating-point output formatting. These manipulators require
including the <iomanip> header file.

2.4 Input with cin


The cin object handles input from the standard input stream. However, it has important behaviors that
programmers must understand to avoid common pitfalls:

• Whitespace Handling: cin stops reading at whitespace characters (spaces, tabs, newlines). This
means 'cin >> name' will only read the first word of a multi-word input.
• Type Extraction: cin extracts as many characters as possible to match the target data type, stopping
at the first incompatible character.
• Buffer Remains: After extraction, any remaining characters (including whitespace) stay in the input
buffer for subsequent reads.
• Failure State: If cin cannot extract a valid value (e.g., reading letters into an integer variable), it
enters a failure state.

2.5 Handling Input Failures


When cin fails to extract valid input, proper error handling is essential. The following pattern demonstrates
how to detect and recover from input failures:

int num;
cin >> num;

if ([Link]()) {
[Link](); // Clear the error state
[Link](numeric_limits<streamsize>::max(), '\n'); // Discard invalid input
cout << "Invalid input! Please enter a valid integer.\n";
}

The [Link]() function resets the error flags, allowing further I/O operations. The [Link]() function
discards characters from the input buffer - the example above discards all characters up to and including
the next newline. This prevents the invalid input from causing problems in subsequent reads.
2.6 Reading Whole Lines: getline() and get()
For reading complete lines of text including spaces, [Link]() and [Link]() are essential. Both functions
read until a newline character, but behave differently regarding that newline:

• [Link](str, n): Reads up to n-1 characters, stops at newline, reads and discards the newline, then
adds null terminator.
• [Link](str, n): Reads up to n-1 characters, stops at newline, but leaves the newline in the input buffer
for subsequent reads.
// Using getline() for complete lines
char name[20];
[Link](name, 20); // Reads entire line including spaces

// Using get() - requires explicit newline handling


[Link](name, 20); // Read line
[Link](); // Consume the remaining newline

3. Data Types
3.1 Basic Data Types
C++ shares the same fundamental data types as C. These types form the building blocks for all data
manipulation in programs. Understanding their sizes and ranges is crucial for writing efficient code and
avoiding overflow errors.

Type Size (typical) Range Use

char 1 byte -128 to 127 Characters, small integers

short 2 bytes -32,768 to 32,767 Small integers

int 4 bytes -2.1B to 2.1B General integers

long 8 bytes Very large range Large integers

float 4 bytes 7 decimal digits General floating-point

double 8 bytes 15 decimal digits Precise floating-point

bool 1 byte true/false Boolean logic

The <climits> header provides constants for type limits: INT_MAX, INT_MIN, SHRT_MAX,
LLONG_MAX, etc. The sizeof operator returns the size in bytes of any type or variable, which is useful
for writing portable code.

3.2 Compound Data Types


Compound data types allow programmers to create more complex data structures by combining basic
types. C++ supports several compound types, most of which are similar to C, but with some important
enhancements:

• Arrays: Collections of elements of the same type stored in contiguous memory.


• Structures: User-defined types that group related variables of different types.
• Unions: Special types where all members share the same memory location.
• Enumerations: User-defined types consisting of named constants.
• Pointers: Variables that store memory addresses of other variables.
• References: Aliases for existing variables (C++ only).
• String Class: A powerful string type from the standard library (C++ only).

4. Structures and Unions


4.1 Structures in C++
Structures in C++ are significantly enhanced compared to C. While C structures can only contain data
members, C++ structures can also contain member functions, making them more powerful for
object-oriented programming.

Key Differences from C:


• Member Functions: C++ structures can have member functions, enabling encapsulation and
methods.
• No struct Keyword Required: When declaring structure variables in C++, the 'struct' keyword is
optional.
• Access Specifiers: C++ structures support public, private, and protected access modifiers (default is
public).
• Constructor Support: Structures can have constructors and destructors for initialization and cleanup.
// C++ Structure with member functions
struct Person {
char name[50];
int age;
float height;

void display() { // Member function


cout << "Name: " << name << ", Age: " << age;
}
};

Person p1 = {"Alice", 25, 175}; // No 'struct' keyword needed


[Link](); // Call member function

4.2 Unions
A union is a special data type that allows storing different data types in the same memory location. All
members of a union share the same memory address, and the union's size equals the size of its largest
member. This makes unions memory-efficient when only one member is needed at a time.

union Data {
short sValue; // 2 bytes
double dValue; // 8 bytes
void printShort() { cout << sValue; }
};

Data data; // Size = 8 bytes (largest member)


[Link] = 42; // Store a short
[Link] = 3.14; // Overwrites sValue!

Important: When one union member is written, all other members become undefined. Reading from a
member that wasn't most recently written leads to undefined behavior. Common applications include
embedded systems, operating systems, and hardware interfaces where memory conservation is critical.

5. String Class
5.1 Two Approaches to Strings
C++ provides two ways to work with strings. The first is the C-style string, inherited from C, which is
simply a character array terminated by a null character ('\0'). The second is the string class from the C++
standard library, which provides a safer, more convenient, and more powerful interface.

5.2 String Class Advantages


• Automatic Memory Management: No need to worry about buffer sizes or null termination.
• Safe Operations: Bounds checking prevents buffer overflows common in C strings.
• Easy Concatenation: Use '+' operator to join strings naturally.
• Rich Methods: Built-in functions for searching, replacing, inserting, and more.
• Dynamic Sizing: Strings automatically grow or shrink as needed.

5.3 Common String Methods

Method Description

length() / size() Returns the number of characters in the string

append(str) Adds characters to the end of the string

insert(pos, str) Inserts a string at the specified position

erase(pos, len) Removes characters starting from position

find(substr) Searches for substring, returns position or -1

replace(pos, len, str) Replaces a portion of the string


substr(pos, len) Returns a substring starting at position

at(index) Returns character at position with bounds checking

empty() Returns true if string is empty

compare(str) Compares two strings lexicographically

5.4 String Operations Example


string s1("12345");
string s2("abcde");

// Concatenation
string s3 = s1 + s2; // "12345abcde"

// Insert
[Link](4, s2); // "1234abcde5"

// Erase
[Link](4, 5); // "12345" (removed 5 chars from pos 4)

// Replace
[Link](1, 3, s1); // "a12345e" (replaced 3 chars from pos 1)

// Access characters
for(int i = 0; i < [Link](); i++)
cout << [Link](i); // Safe access with bounds checking
cout << s1[i]; // Direct access (no bounds checking)

6. Reference Variables
6.1 What is a Reference?
A reference variable is an alias (alternative name) for an existing variable. Once a reference is initialized to
refer to a variable, it cannot be changed to refer to another variable. References provide a convenient way
to work with variables without the syntax complexity of pointers.

Key Properties:
• References must be initialized when declared - they cannot be declared without initialization.
• After initialization, a reference cannot be reassigned to refer to a different variable.
• A reference and its target variable share the same memory address.
• Any operation on the reference affects the original variable directly.
• References are essentially syntactic sugar for constant pointers with automatic dereferencing.
int rats = 10;
int & rodents = rats; // rodents is an alias for rats
int * prats = &rats; // prats is a pointer to rats
// rodents is essentially equivalent to:
// int * const rodents = &rats;
// But with automatic dereferencing

6.2 Reference vs Pointer

Aspect Reference Pointer

Initialization Must be initialized Can be uninitialized

Reassignment Cannot be reassigned Can be reassigned

Null value Cannot be null Can be null (nullptr)

Memory address Same as target Stores address of target

Dereferencing Automatic Requires * operator

Arithmetic Not allowed Allowed (++, --, +n)

6.3 References as Function Parameters


One of the most important uses of references is for passing arguments to functions. This technique, called
'passing by reference', allows functions to modify the original arguments directly. This is particularly
useful when you need to return multiple values or modify large data structures efficiently.
// Swap using references - modifies original variables
void swap(int &a;, int &b;) {
int temp = a;
a = b;
b = temp;
}

int x = 5, y = 10;
swap(x, y); // x is now 10, y is now 5

6.4 When to Use Reference Arguments


• To modify caller's data: When a function needs to change the original variables passed to it.
• For efficiency: Passing large objects by reference avoids copying, improving performance.
• With const: Use 'const Type&' to pass efficiently while preventing modification.
// Efficient, safe passing with const reference
double calVolume(const double& side) {
return side * side * side; // Cannot modify 'side'
}

7. Dynamic Memory Allocation


7.1 Overview
Dynamic memory allocation allows programs to request memory at runtime rather than at compile time.
This is essential when the memory requirements cannot be determined in advance, such as when dealing
with user input or variable-sized data structures. In C++, the 'new' and 'delete' operators replace C's
malloc() and free() functions with a safer, type-aware interface.

7.2 The new Operator


The 'new' operator allocates memory dynamically and returns a pointer to the allocated memory. For single
variables, use 'new typeName'. For arrays, use 'new typeName[size]'. The allocated memory is
uninitialized (contains garbage values) unless explicitly initialized.

// Allocate single variable


int* pt = new int;
*pt = 42;

// Allocate with initialization (C++11)


int* pt2 = new int(42);

// Allocate array
int size = 10;
int* arr = new int[size]; // Dynamic array

7.3 The delete Operator


The 'delete' operator deallocates memory previously allocated by 'new'. Failing to delete dynamically
allocated memory causes memory leaks, where the program consumes increasing memory over time.
Always pair each 'new' with a corresponding 'delete'.
// Free single variable
delete pt;
pt = nullptr; // Prevent dangling pointer

// Free array - note the brackets


delete[] arr;
arr = nullptr;

7.4 Best Practices and Common Mistakes


• Always match new with delete: Every allocation must have a corresponding deallocation.
• Use delete[] for arrays: Using 'delete' instead of 'delete[]' for arrays leads to undefined behavior.
• Set pointers to nullptr after delete: This prevents 'dangling pointers' that reference freed memory.
• Don't delete non-dynamic memory: Never use 'delete' on stack-allocated variables or addresses not
from 'new'.
• Avoid double deletion: Calling 'delete' twice on the same address corrupts memory.
// CORRECT usage
int* pt = new int;
delete pt;
pt = nullptr;
// WRONG - double delete
int* pt = new int;
delete pt;
delete pt; // ERROR: undefined behavior

// WRONG - deleting stack memory


int x = 5;
int* px = &x;
delete px; // ERROR: x is not dynamically allocated

8. Functions
8.1 Inline Functions
Inline functions are a C++ optimization feature designed to reduce the overhead of function calls. When a
function is declared 'inline', the compiler attempts to replace the function call with the actual function code
at compile time. This eliminates the overhead of jumping to a different memory location, saving
parameters on the stack, and returning to the caller.

When to Use Inline:


• Small, frequently-called functions where call overhead is significant relative to execution time.
• Functions with simple logic that can be quickly executed.
• Performance-critical code sections where every cycle counts.

When NOT to Use Inline:


• Large functions where code bloat outweighs the call overhead savings.
• Functions with loops or complex control structures.
• Recursive functions (cannot be effectively inlined).
inline double square(double x) { return x * x; }

int main() {
double a = square(5.0); // Compiler may replace with: a = 5.0 * 5.0;
return 0;
}

Note: The 'inline' keyword is a suggestion to the compiler, not a command. The compiler may ignore the
inline request if the function is too complex, and conversely, may inline small functions even without the
keyword (automatic inlining).

8.2 Default Arguments


Default arguments allow functions to be called with fewer arguments than they are defined to accept.
When an argument is omitted in a function call, the default value is automatically used. This feature
simplifies function interfaces while maintaining flexibility.

Rules for Default Arguments:


• Default values must be specified from right to left - you cannot have a default for an argument if any
argument to its right lacks a default.
• Arguments are assigned from left to right in function calls - you cannot skip arguments in the
middle.
• Default values should be specified in the function declaration (prototype), not in both declaration
and definition.
• Default arguments can only be specified once - either in declaration or definition, not both.
// Valid - defaults from right to left
int add(int x, int y = 5, int z = 6);

// Invalid - missing defaults to the right


// int add(int x = 1, int y, int z = 6); // ERROR

// Function calls
add(10, 20, 30); // All explicit: 10+20+30 = 60
add(10, 20); // z default: 10+20+6 = 36
add(10); // y,z default: 10+5+6 = 21
// add(10, , 30); // ERROR: cannot skip y

8.3 Function Overloading


Function overloading allows multiple functions to share the same name, provided they have different
parameter lists. This is also called function polymorphism. The compiler determines which version to call
based on the arguments passed. This enables intuitive function naming and cleaner code.

Valid Overloading (Different Signature):


// Different parameter types
int add(int x, int y);
float add(float x, float y);

// Different number of parameters


int add(int x, int y);
int add(int x, int y, int z);

// const difference
void process(char* str);
void process(const char* str); // Different signature

Invalid Overloading:
• Same parameter names: 'int add(int x, int y)' and 'int add(int a, int b)' are the same signature.
• Return type only: 'int add(int, int)' and 'void add(int, int)' cannot coexist - return type is not part of
signature.
• Ambiguous match: 'double cube(double x)' and 'double cube(double& x)' - compiler cannot
distinguish when called with a variable.

8.4 Function Templates


Function templates allow you to write generic functions that work with multiple data types. Instead of
writing separate overloaded functions for each type, a single template can handle all compatible types. The
compiler generates the appropriate function code based on the types used in each call.

template <typename T> // or template <class T>


T getMax(T a, T b) {
return (a < b) ? b : a;
}

// Compiler generates appropriate versions:


int i = getMax(5, 10); // getMax<int>
double d = getMax(3.14, 2.72); // getMax<double>
char c = getMax('a', 'z'); // getMax<char>

Template Syntax:
• template <typename T> or template <class T>: Declares a template with type parameter T.
• Multiple type parameters: template <typename T, typename U> allows multiple generic types.
• Template instantiation: The compiler creates specific function versions based on argument types.
• Type deduction: The compiler can usually deduce template arguments from function arguments.
// Template for swapping any type
template <typename T>
void Swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}

int x = 5, y = 10;
Swap(x, y); // Swaps integers

string s1 = "Hello", s2 = "World";


Swap(s1, s2); // Swaps strings

Summary: Key Takeaways


This lecture introduced fundamental C++ programming concepts that form the foundation for more
advanced topics. Below is a summary of the essential points you should remember from each section:

• C++ vs C: C++ is a superset of C that adds object-oriented and generic programming features. It
supports three programming paradigms: procedural, object-oriented, and generic.
• Input/Output: Use 'cout' for output with '<<' operator and 'cin' for input with '>>' operator.
Namespaces prevent naming conflicts. Handle input failures with [Link]() and [Link]().
• Data Types: C++ has the same basic types as C but adds compound types with enhanced features.
Structures can have member functions, and the string class provides safe string operations.
• References: References are aliases that must be initialized. Use them for passing by reference to
modify caller's data or for efficient passing of large objects.
• Dynamic Memory: Use 'new' to allocate and 'delete' to free memory. Always match allocations with
deallocations and set pointers to nullptr after deletion.
• Inline Functions: Use for small, frequently-called functions to eliminate call overhead. The compiler
may ignore inline requests for large functions.
• Default Arguments: Specify from right to left in function declarations. Arguments are assigned from
left to right in calls - you cannot skip arguments.
• Function Overloading: Multiple functions can share a name if they have different parameter lists
(different types or numbers of parameters).
• Function Templates: Write generic functions that work with multiple types using template syntax.
The compiler generates type-specific versions automatically.

Reference Textbook: Prata, Stephen. C++ Primer Plus, 5th Edition, Sams Publishing, 2002. Relevant
chapters: 1, 2, 3, 4, 8.

You might also like