Table of Contents
- What is C++
- C++ Keywords (C++98)
- Namespaces
- Namespace Usage
- C++ Input & Output
- Default Parameters
- Function Overloading
- References
- Inline Functions
What is C++
C++ is an object-oriented high-level programming language that was developed based on the foundations of the C language.
C++ Keywords (C++98)
C++ contains a total of 63 keywords, while the C language has 32 keywords.
Note: The following section only shows how many keywords C++ has without providing detailed explanations for each keyword.
Namespaces
In C/C++, variables, functions, and classes (to be covered later) exist in large quantities. These identifiers all reside in the global scope, which can lead to numerous conflicts. The purpose of using namespaces is to localize identifier names and avoid naming collisions or namespace pollution. The namespace keyword was introduced specifically to address this issue.
To define a namespace, you use the namespace keyword followed by the namespace name, then a pair of curly braces {}. The members of the namespace are enclosed within these braces.
namespace Utilities
{
// Variables, functions, and types can be defined within a namespace
int counter = 10;
int Multiply(int left, int right)
{
return left * right;
}
struct ListNode
{
struct ListNode* next;
int value;
};
}
// Namespaces can be nested
namespace Outer
{
int firstValue;
int secondValue;
int Add(int left, int right)
{
return left + right;
}
namespace Inner
{
int thirdValue;
int fourthValue;
int Subtract(int left, int right)
{
return left - right;
}
}
}
Important: A namespace defines a new scope. All content within a namespace is limited to that namespace's scope.
Namespace Usage
Method 1: Using the Namespace Name with Scope Resolution Operator
int main()
{
printf("%d\n", Outer::firstValue);
return 0;
}
Method 2: Using using to Introduce Specific Members
using Outer::secondValue;
int main()
{
printf("%d\n", Outer::firstValue);
printf("%d\n", secondValue);
return 0;
}
Method 3: Using using namespace to引入 the Entire Namespace
using namespace Outer;
int main()
{
printf("%d\n", Outer::firstValue);
printf("%d\n", secondValue);
Add(10, 20);
return 0;
}
C++ Input & Output
#include <iostream>
// std is the namespace name for the C++ standard library
// All standard library definitions are placed within this namespace
using namespace std;
int main()
{
cout << "Hello world!!!" << endl;
return 0;
}
Key Points:
- To use
cout(standard output object to console) andcin(standard input object from keyboard), you must include the<iostream>header file and use thestdnamespace. coutandcinare global stream objects, whileendlis a special C++ symbol representing a line break. All are included in the<iostream>header.- The
<<operator is the stream insertion operator, and>>is the stream extraction operator. - C++ input/output is more convenient than printf/scanf because it automatically recognizes variable types without requiring manual format specification.
#include <iostream>
using namespace std;
int main()
{
int userAge;
double accountBalance;
char grade;
// Automatic type recognition
cin >> userAge;
cin >> accountBalance >> grade;
cout << userAge << endl;
cout << accountBalance << " " << grade << endl;
return 0;
}
Best Practices for Using the std Namespace
std is the namespace for the C++ standard library. Here are guidelines for using it appropriately:
- For everyday practice and exercises, using
using namespace stddirectly is convenient and acceptable. - However, this approach exposes all standard library definitions. If you define types, objects, or functions with names that conflict with the library, issues will arise. This rarely occurs in practice exercises but becomes more likely in large-scale projects. For professional development, consider using explicit namespace specification like
std::coutor selectively importing specific members withusing std::cout.
Default Parameters
A default parameter is a specified value assigned to a function's parameter during declaration or definition. When calling the function, if no argument is provided, the default value is used; otherwise, the specified argument is used.
void DisplayMessage(string text = "Default message")
{
cout << text << endl;
}
int main()
{
DisplayMessage(); // Uses default parameter
DisplayMessage("Custom"); // Uses provided argument
return 0;
}
Types of Default Parameters
Full Default Parameters
void ConfigureSettings(int timeout = 30, int retries = 3, bool enabled = true)
{
cout << "Timeout: " << timeout << endl;
cout << "Retries: " << retries << endl;
cout << "Enabled: " << enabled << endl;
}
Partial Default Parameters
void ProcessData(int identifier, int maxCount = 100, char delimiter = ',')
{
cout << "ID: " << identifier << endl;
cout << "Max count: " << maxCount << endl;
cout << "Delimiter: " << delimiter << endl;
}
Important Notes:
- Partial default parameters must be specified from right to left in sequence and cannot be specified intermittently.
- Default parameters cannot appear simultaneously in both function declaration and definition.
- Default values must be constants or global variables.
- C language does not support default parameters (not supported by compilers).
Function Overloading
In natural language, a single word can have multiple meanings, and people determine the intended meaning based on context. This concept of one name having multiple meanings is called overloading.
Function Overloading is a special case in C++ where multiple functions with similar functionality can share the same name within the same scope. These functions must differ in their parameter lists (different number of parameters, different types, or different type ordering). This feature is commonly used to handle similar operations on different data types.
Example: Different Parameter Types
int CalculateSum(int first, int second)
{
cout << "int CalculateSum(int first, int second)" << endl;
return first + second;
}
double CalculateSum(double first, double second)
{
cout << "double CalculateSum(double first, double second)" << endl;
return first + second;
}
Example: Different Number of Parameters
void LogMessage()
{
cout << "LogMessage()" << endl;
}
void LogMessage(int severity)
{
cout << "LogMessage(int severity)" << endl;
}
Example: Different Parameter Type Ordering
void Initialize(int id, char code)
{
cout << "Initialize(int id, char code)" << endl;
}
void Initialize(char code, int id)
{
cout << "Initialize(char code, int id)" << endl;
}
References
A reference is not a newly defined variable but rather an alias for an existing variable. The compiler does not allocate separate memory space for a reference; it shares the same memory space with the variable it references.
For example, a person named "John Smith" might be called "Johnny" by family and "J.S." by colleagues at work.
Syntax: Type &referenceName = referenceEntity
void ReferenceDemo()
{
int originalValue = 42;
int& referenceValue = originalValue; // Define reference
printf("%p\n", &originalValue);
printf("%p\n", &referenceValue); // Same address
}
Note: The reference type must be the same type as the reference entity.
Reference Characteristics
- References must be initialized at the time of definition.
- A variable can have multiple references.
- Once a reference is bound to an entity, it cannot reference a different entity.
void MultipleReferences()
{
int data = 100;
int& ref1 = data;
int& ref2 = data;
printf("%p %p %p\n", &data, &ref1, &ref2); // All same address
}
Const References
void ConstReferenceDemo()
{
const int constantValue = 50;
// int& invalidRef = constantValue; // Error: cannot bind non-const reference to const
const int& validRef = constantValue; // OK
// int& literalRef = 100; // Error: cannot bind reference to literal
const int& literalRef = 100; // OK
double floatingPoint = 99.99;
// int& typeMismatch = floatingPoint; // Error: type mismatch
const int& convertedRef = floatingPoint; // OK (creates temporary)
}
Common Usage Scenarios
1. As Function Parameters
void SwapValues(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
2. As Return Values
int& GetCounter()
{
static int counter = 0;
counter++;
return counter;
}
Efficiency Comparison: Pass by Value vs Pass by Reference
When using pass-by-value for parameters or return types, the function does not directly pass the actual variable or return the variable itself. Instead, it creates a temporary copy. Therefore, using pass-by-value is significantly less efficient, especially when dealing with large data types.
References vs Pointers
Conceptual Level: From a syntax perspective, a reference is simply an alias without its own separate memory space. It shares the same space as the entity it references.
int main()
{
int value = 10;
int& alias = value;
cout << "Address of value: " << &value << endl;
cout << "Address of alias: " << &alias << endl;
return 0;
}
Implementation Level: At the underlying level, references do have memory allocated because references are implemented using pointers.
Key Differences Between References and Pointers
- References conceptually define an alias for a variable, while pointers store a variable's address.
- References must be initialized when defined, while pointers have no such requirement.
- Once a reference is initialized to reference an entity, it cannot reference a different entity, while pointers can point to any compatible entity at any time.
- There is no NULL reference, but there are NULL pointers.
- Size semantics differ in sizeof: For references, sizeof returns the size of the referenced type, while for pointers, it always returns the size of a memory address (4 bytes on 32-bit systems).
- Incrementing a reference increments the referenced entity, while incrementing a pointer moves it forward by the size of the referenced type.
- There are multi-level pointers, but there are no multi-level references.
- Access methods differ: Pointers require explicit dereferencing, while references are handled automatically by the compiler.
- References are generally safer to use than pointers.
Inline Functions
A function decorated with the inline keyword is called an inline function. During compilation, the C++ compiler expands the function at the call site, eliminating the overhead of function call stack frame creation. This approach improves program runtime efficiency.
Characteristics
inlineis a space-for-time tradeoff. When the compiler processes a function as an inline function, it replaces the function call with the function body. The trade-off is potential increase in executable size, but the benefit is reduced call overhead and improved runtime efficiency.- For the compiler,
inlineis merely a suggestion. Diffferent compilers may implement inline differently. General recommendation: Useinlinefor functions that are small (not long), non-recursive, and called frequently. Otherwise, the compiler may ignore the inline suggestion. - It is not recommended to separate declarations and definitions for inline functions, as this can cause linking errors. Since inline functions are expanded at compile time, they have no address, making it impossible for the linker to find them.