5.9 KiB
Exercises
Task 01
Install G++ and Clang, then compile the provided file hello.cpp
.
Use the following flags when compiling:
-std=c++17 -Wall -Wextra -O2
Next, set up Boost on your system and compile the provided file hello_boost.cpp
.
Boost is quite common and provides you a set of useful C++ libraries.
Some of its content is even promoted into the C++ standard library.
Task 02
Run Clang on the provided file vec.cpp
using the following command:
clang -std=c++17 -Xclang -ast-dump -fsyntax-only -Wno-vexing-parse vec.cpp
Clang will parse the input file and display its abstract syntax tree (AST).
In the bottom half of the output you'll find the function declaration of main
followed by its CompoundStmt
.
Take a close look at its children and compare the resulting AST with the input code.
Notice any oddities — something that looks counter intuitive?
As you can see, there are multiple different ways of initialisation in C++. Check out the corresponding section at cppreference.
Task 03
The directory task03
hosts four subdirectories, libFoo
, libBar
, libBaz
, and app
.
Each folder prefixed with lib
represents a library and contains a header plus a source file.
Furthermore, the library libBaz.so
depends on libBar.so
.
app
contains a single source file providing a main
function.
It depends on all three libraries.
- Model this project structure using CMake
- Be sure to set the C++ standard to C++17 and enable warnings (
-Wall -Wextra
) - The default build type should be Release
CMake itself is a build system generator. You can choose from a variety of target build systems.
Task 04
Examine the program iterations.cpp
and think about the expected output.
Compile the program and run it.
What do you notice?
Did you expect this behaviour?
Did you get any compiler warnings?
Investigate what is actually happening (consider using valgrind
or a debugger).
How can such errors be prevented? Look for tools (e.g. static code analysers) which help discovering such faulty code.
Note: If you run the executable and everything seems normal, try changing the initial content of xs
, using different optimisation flags, or a different compiler.
The actual behaviour of this executable depends on various factors.
Task 05
You are given the program strange.cpp
.
Compile it with different compilers and optimisation flags.
What do you notice?
What is really happening here?
See Undefined Behaviour and Defining the undefinedness of C.
Task 06
This task focuses on the correct implementation of RAII as well as copy and move semantics.
You are asked to implement the concept of unique_ptr
and shared_ptr
.
Since we won't concern ourselves with templates for the moment your implementation will own an instance of the following struct
.
struct Vec2 {
float x, y;
};
- Read the documentation regarding smart pointers,
unique_ptr
, andshared_ptr
- Implement your version of
unique_ptr_to_vec2
andshared_ptr_to_vec2
fulfilling these requirements:- Dynamically allocate an instance of
Vec2
in your constructor - De-allocate the
Vec2
instance in your destructor - Implement correct copy semantics (copy constructor / copy assignment)
- Implement correct move semantics (move constructor / move assignment)
- Enable access to
Vec2
via the operators*
and->
- Thread-safety for
shared_ptr_to_vec2
's reference counter is not required - Pay attention to corner-cases like self-assignment (
v = v
)
- Dynamically allocate an instance of
- Prepare a few interesting test cases
- Check your implementation for memory leaks and memory corruptions using
valgrind
and sanitizers
See Rule of Three.
Task 07
Read this blog post.
- Pay attention to implementation vs. interface inheritance
- Pay attention to the use of templates (assuming you've already covered them)
- Think about the benefits and drawbacks of the used patterns
Task 08
You are given the following definition of a person:
struct Person {
std::string firstname;
std::string lastname;
int age;
};
- Implement relational operators (
<
,<=
,>
,>=
) - Implement comparison operators (
==
,!=
)
Next, create 5 different instances and put all of them
- in an
std::vector
; - in an
std::set
; and - in an
std::map
as key (we don't care about the value type of the map).
Use algorithms from the standard library, like std::find
and std::partition
on these containers and examine which operators are used.
Hint: You may want to have a look at std::tie
.
Task 09
Reuse Person
from Task 08 and implement the necessary parts for inserting it into an std::unordered_set
.
Compare the performance of:
std::vector
std::list
std::set
std::unordered_set
Task 10
Have a look at this. Now, do that in C++!
Utilize lambdas, std::function
, and/or structs with call operators.
Critically think about ownership and minimize the amount of heap allocations.
Task 11
Take a look at Boost's chat server example.
Try to understand how the session's lifetime is managed by the server.
Focus on std::enable_shared_from_this
in combination with lambda captures.