Learncpp: 01 Functions and Files
Function Return Values
- The
main()function must return anint. - Explicit function calls to
main()should be avoided. - Most compilers detect missing return values, but in complex cases, they might fail to do so.
- Nested functions are not allowed in C++.
Function Parameters and Arguments
- A parameter is a variable in a function’s header. It behaves like a regular variable but is initialized with a value provided by the caller.
- An argument is the actual value passed to a function when calling it.
- When a function is called:
- Parameters are created as variables.
- Argument values are copied into parameters (pass by value).
- These parameters are called value parameters.
- Unreferenced parameters exist but are not used in the function body.
- Unnamed parameters are parameters without a name.
Local Scope
- Local variables are declared inside a function and only accessible within that function.
- Creation & Destruction:
- Created when execution reaches their definition.
- Destroyed when they go out of scope (end of
{}block).
- Scope & Lifetime:
- Scope defines where a variable is accessible.
- Lifetime lasts from creation to destruction.
- Temporary objects (e.g., function return values) exist briefly and are often optimized away in modern compilers.
The One Definition Rule (ODR)
C++ enforces one definition per entity across a program. ODR consists of three key rules:
- Within a file:
- Each function, variable, type, or template must have only one definition in a given scope.
- Definitions in separate scopes (e.g., different namespaces) are fine.
- Within a program:
- Each function or variable must have only one definition across files.
- If multiple files define the same function/variable, it causes linker errors.
- Local variables and functions marked
staticorinlineare exceptions.
- Multiple identical definitions are allowed for:
- Types, templates, inline functions, and inline variables.
- As long as each definition is identical across translation units.
Namespaces
- A scope region ensures identifiers remain distinct from names declared elsewhere.
- A namespace introduces a new scope for identifiers, preventing conflicts.
- If an identifier isn’t inside a class, function, or namespace, it belongs to the global namespace.
- The
::symbol is the scope resolution operator. -
A using directive allows access to namespace members without a prefix:
using namespace std; // Avoid in large projects
The Preprocessor
- After preprocessing, a file becomes a translation unit.
- Preprocessor directives:
- Start with
#and end with a newline (and not with a semicolon). - Example:
#include,#define,#if.
- Start with
- Macros (
#define):-
Define object-like macros:
#define IDENTIFIER #define IDENTIFIER substitution_text - Macros replace occurrences of
IDENTIFIERwithsubstitution_text. - Function-like macros are discouraged.
-
- Conditional Compilation:
#include <iostream> #define PRINT_JOE int main() { #ifdef PRINT_JOE std::cout << "Joe\n"; // Compiled #endif #ifdef PRINT_BOB std::cout << "Bob\n"; // Skipped #endif return 0; } -
#if 0for commenting out blocks:#include <iostream> int main() { std::cout << "Joe\n"; #if 0 // Disable this section std::cout << "Bob\n"; std::cout << "Steve\n"; #endif return 0; }- Useful for disabling code blocks as nesting multiline (
/* */) comments is not allowed.
- Useful for disabling code blocks as nesting multiline (
- Scope of
#define: Preprocessor directives execute before compilation, top to bottom.
Header Files
- A source file should include its paired header:
- Helps catch errors at compile time instead of link time.
- If a function’s return type differs in declaration and definition, the compiler throws an error.
- Overloaded functions (same name, different parameters) are not caught at this stage.
- Some necessary definitions may be in the header, making it mandatory to include.
- Angled Brackets (
<>) vs. Double Quotes (""):-
#include <file>: Searches system directories (used for standard headers). -
#include "file": Searches current directory first, then system directories.
-
- Why doesn’t
<iostream>have.h?- Old C++ standard used
<iostream.h>, which defined everything in the global namespace. - The ANSI committee moved all standard library identifiers into the
stdnamespace. - New-style headers omit
.hto differentiate from old headers.
Header Type Naming Convention Example Namespace C++ Specific (New) <xxx><iostream>stdC Compatibility (New) <cxxx><cstddef>std(required), global (optional)C++ Specific (Old) <xxx.h><iostream.h>Global C Compatibility (Old) <xxx.h><stddef.h>Global (required), std(optional) - Old C++ standard used
-
Including headers from other directories:
g++ -o main -I./source/includes main.cpp
Enjoy Reading This Article?
Here are some more articles you might like to read next: