Home | About | Blog | Projects | Contact
Continuing with C++ Primer (5th Edition) by Lippman, Lajoie, and Moo. Today covering Chapter 6 (Functions). Skipped Chapters 4 and 5 (Expressions and Statements).
Function definition consists of return type, a name, a list of zero or more parameters, and a body. The body is the actions that the function performs in the statement block
In C++ names have scope, and objects have lifetime.
Scope determines the visibility of variables, while lifetime determines how long they exist in memory.
static: variables declared with static keyword maintain their state between function calls. Each local static object is initialized before the first time execution passes through the objects definition. Local statics are not destroyed when a function ends; they are destroyed when the program terminates.
Parameter initialization works the same way as variable initialization When a parameter is a reference, we say that its corresponding argument is "passed by reference" or that the function is "called by reference." When the argument value is copied, the parameter and argument are independent objects. We say such arguments are "passed by value" or that the function is "called by value."
Use references to avoid copies of large objects, such as using a function to compare 2 strings. Use const references when you don't want the function to modify the argument.
Use reference to const when possible: It is common mistake to define parameters that a function does not change as (plain) references. Using a reference instead of a reference to const unduly limits the type of arguments that can be used with the function.
Key Differences Between initializer_list and Ellipsis:
initializer_list<T>:
Ellipsis (...):
When to Use Ellipsis:
How Ellipsis Works:
va_list: type to hold argument informationva_start(list, last_named): initialize to first unnamed argva_arg(list, type): get next argument as specified typeva_end(list): cleanup (required!)Never return a reference or pointer to a local object
Whether a function call is an lvalue or rvalue depends on the return type of the function
A call to a function that returns a reference can be used in the same ways as any other lvalue
c++11 feature: Functions can return a braced list of values. Ex: returning a vector<int> from a function
I read about returning pointers, trailing return types, using decltype for auto-deducing return types, and overloading functions
const_cast is most useful in overloaded functions.
Default Arguments:
Inline and constexpr Functions:
inline and constexpr functions may be defined multiple times in the program
assert:
NDEBUG:
assert checks in the code.A pointer to a function is a variable that stores the memory address of a function, allowing you to call that function indirectly.
Why Use Function Pointers?
Basic Syntax:
The declaration looks like: int (*funcPtr)(int, int);
Breaking this down:
int - the return type(*funcPtr) - "funcPtr is a pointer to..."(int, int) - "...a function that takes two int parameters"Important: Without parentheses, int *funcPtr(int, int) would be a function that returns an int*, not a pointer to a function!
Using Function Pointers:
funcPtr = &add; or simply funcPtr = add;)funcPtr(5, 3) or (*funcPtr)(5, 3))Common Use Case - Callbacks: Function pointers are often passed as parameters to other functions, allowing you to customize behavior. For example, a sorting function could accept a comparison function pointer to determine sort order.
Modern Alternative: C++11 introduced std::function which provides a cleaner, more flexible way to work with function pointers and other callable objects.
//Exercise 6.17: Write a function to determine whether a string contains any capital letters.
bool hasCapitalLetters(const string &s){
for(auto i = s.begin(); i != s.end(); i++){
if (isupper(*i)) return true;
}
return false;
}
//Exercise 6.17: Write a function to change a string to all lowercase.
void makeLowercase(string &s) {
for(auto i = s.begin(); i != s.end(); i++){
if (isupper(*i)) *i = tolower(*i);
}
}
//These functions do not have the same types because one function only needs to read the string, and the other modifies it.
//There for the const is for the read only string. We passed references so that we did not have to make copies of the strings for the functions.
//Exercise 6.33: Write a recursive function to print the contents of a vector
void recur_print_vector(const vector &vec){
static auto it = vec.begin();
if(it != vec.end()){
cout << *it++ << endl;
recur_print_vector(vec);
}
}
Exercise 6.31: When is it valid to return a reference from a function? A reference to const?