template: titleslide
template: titleslide
-
You are a decent programmer in another language
-
You know how to use the shell
-
You have access to a terminal in front of you with a C++ compiler
Writing efficient software, more than anything, requires you to choose an appropriate algorithmic approach for your problem.
Here we want to take a lower-level approach and talk about how to implement patterns efficiently using C++.
???
For lots on how to do this well, consider other courses such as the Parallel Design Patterns course from the MSc
Both HPC and data science, when you actually come to running a program, are about getting a large amount of data from memory to a core, doing something useful to it, and storing it again.
This is why FORTRAN is still relevant!
But it does force you to confront this all time.
C++ is all about building abstractions and composing them.
![:thumb](I will talk about a few and give some suggestions of default rules)
We could spend a whole semester going in depth on C++, so we've picked a handful of features to cover that you really need to write modern C++ for technical computing.
This is not trying to teach the whole language in the many different styles that people have developed over the decades.
Please ask questions any time!
By Universal Studios - Dr. Macro, Public Domain, https://commons.wikimedia.org/w/index.php?curid=3558176
-
Large: the C++20 standard is just over 1800 pages
-
Composed of many parts: C, classes, generics, functional programming, exceptions, the vast library, ...
-
Inspires dread in those do not understand it
-
Dangerous:
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
- "Expert friendly"
"C++ is an octopus made by nailing extra legs onto a dog" - Steve Taylor
But you can cut off some extra legs to get the right dog for your program!
???
Why is it called C++20?
Because that's how many legs they had to nail on to "fix" the octopus.
-
General purpose
-
Flexible by allowing developers to build abstractions (and provides a large number through the library)
-
Performance and efficiency are always targeted "you only pay for what you use"
-
Use the powerful type system to express intent
-
Communicate with the reader, not the compiler
C++ is a work in progress.
Every three years there is a new update to the International Standard
Latest one, C++20, still not fully implemented by an compiler. Major new features are ranges, coroutines, concepts, and modules
Next one, in 2023, well underway. Major features likely to include networking, string formating, executors, and consolidation of new C++20 features
-
Bjarne Stroustrup, "Programming: Principles and Practice Using C++" (2nd Ed.). Assumes very little but it's long
-
Bjarne Stroustrup, "A Tour of C++". Assumes you're an experience programmer and is quite brief - targets C++17
-
Best online reference is http://en.cppreference.com/ (comes in other human languages too!)
-
Scott Meyers, "Effective Modern C++", 2014. This is the book to get once you know your way around C++, but you want to improve. Teaches lots of techniques and rules of thumb for writing correct, idiomatic, maintainable code.
-
stackoverflow.com has a lot of good questions about C++ (look for ones with at least 100 up-votes).
template: titleslide
name: hello
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
}
template: hello
$ g++ --std=c++17 hello.cpp -o hello
$ ./hello
Hello, world!
template: hello
-
The preprocessor runs first
-
The
#include
directive copies the contents of another file into the current compilation unit. -
The angle brackets
<...>
tell it to look only in system directories. -
This includes the
iostream
standard library header
template: hello
-
Every program must have exactly one main function.
-
The compiler and OS arrange for this to be called when you run it.
-
(Not shown, but you can also get the command line arguments)
template: hello
-
std
is the standard library namespace. -
A namespace allows scoping of names (much like a filesystem has directories).
-
The scope resolution operator
::
lets us access something from inside a namespace. -
cout
represents console output (i.e. standard output / stdout)
template: hello
-
The standard library uses the bitwise left shift operator (
<<
) to mean stream insertion -
I.e. output the right hand side to the left.
-
Every statement in C++ must be terminated with a semicolon (
;
) -
The language treats all whitespace (space, tab, line break) the same
template: titleslide
You can use your laptop, Cirrus, or ARCHER2
Your machine : you need a C++ compiler that supports at least C++17. If you use Windows and MSVC we may not be able to help much... Sorry!
Cirrus: You have log in details.
Once connected you need to load the up-to-date compilers:
module load gcc/8.2.0
ARCHER2: You have log in details.
Once connected you need to load the up-to-date compilers:
module load gcc/10.2.0
All these slides and the exerices are available on GitHub: https://github.com/EPCCed/APT-CPP
You also can view the slides and other materials in a browser by going to https://EPCCed.github.io/APT-CPP/
In the terminal, you need to use git get a copy of the exercises:
git clone https://github.com/EPCCed/APT-CPP
Then you can change to the directory with this simple program
cd APT-CPP/lectures/cpp-intro/hello
View the program source
vim hello.cpp
emacs hello.cpp
Compile the program:
g++ --std=c++17 hello.cpp -o hello
No output means success!
Run it:
./hello
template: titleslide
-
It is a typed language - all variables must be declared
- But you can often tell the compiler to figure out the type
-
Counts from zero (like C, Python) not from one (like Fortran)
template: titleslide
A variable is
- an object
or
- a reference
that is declared to have a type and a name.
???
We'll talk about references later
An object is a region of storage that has:
- type
- size
- value
- lifetime
???
types are next, explain a bit about the others
template: titleslide
"Objects and expressions have a property called type, which both restricts the operations that are permitted for those entities and provides semantic meaning to the otherwise generic sequences of bits." -- https://en.cppreference.com
Type | Description |
---|---|
void |
Nothing - used to indicate a function returns no value. |
bool |
true or false |
int |
Standard signed integer for your machine. At least 16bits. Usually 32 bits. |
double |
Double-precision floating point. Usually an IEEE 754 64 bit number. |
std::byte |
Raw untyped memory |
There are also unsigned
versions of the integer types
The header <cstdint>
provides fixed-width integer types available on
your implementation: e.g. std::int32_t
and std::uint64_t
.
???
There are others:
- single precision floats
- short/long/long long ints
Go look them up on CPP Reference as you need to
The standard library has a class* called string
that holds a string
of text characters.
You have to #include <string>
to use it which includes the "header
file" that contains all the information the compiler needs to let you
use it.
#include <iostream>
#include <string>
int main() {
std::string message = "Hello, world";
std::cout << message << std::endl;
}
??? Character encoding in the standard library is a bit of a mess.
Partially fixed in C++20
Find a library if you need to do serious text handling because Unicode is super complicated
template: titleslide
A function encapsulates a piece of code between braces (curly
brackets, {}
) and gives it a name so you can use it later.
void say_hello() {
std::cout << "Hello, world!" << std::endl;
}
int main(int argc, char* argv[]) {
say_hello();
}
???
You declare function by first giving the return type (void
)
Then the name (say_hello
)
Then the list of zero or more parameters
You must declare the return type and parameter types.
Parameters are local variables that are initialised by the caller.
Return a value with the return
statement - the type of the
expression must be (convertible to) the declared return type.
int sum(int a, int b) {
return a + b;
}
Can alse use trailing return type (aka "east end functions"):
auto sum(int a, int b) -> int {
return a + b;
}
???
First sight of the auto
keyword - this basically says to the
compiler: "figure it out from what follows"
In this case, by us telling it later
To use a function - to "call" it - you give its name and then provide the arguments in parentheses
int main () {
int x = 42;
std::cout << "Total = " << sum(x, 100) << std::endl;
}
The parameters to the function must match the (a) declaration.
You can have multiple functions with the same name but different arguments.
int sum(int a, int b) {
return a + b;
}
double sum(double a, double b) {
return a + b;
}
When you call sum
, the compiler knows the types of the arguments and
will try to find the best match from all the candidates with the name.
The compiler will also try to use any built-in or user-defined conversion rules.
int i1 = 1;
int i2 = 2;
double d1 = 1.0;
double d2 = 2.0;
unsigned u42 = 42;
std::string name = "Alice";
std::string file = "data.csv";
std::cout << sum(i1, i2) << std::endl;
std::cout << sum(3, 72) << std::endl;
std::cout << sum(i1, u42) << std::endl;
std::cout << sum(d2, d1) << std::endl;
std::cout << sum(d2, 1e6) << std::endl;
std::cout << sum(d2, i1) << std::endl;
std::cout << sum(name, file) << std::endl;
C++ operators, for the non-fundamental types, are just functions with odd names, e.g.:
std::string operator+(const std::string& a, const std::string& b);
You can then use the natural syntax when manipulating these in other code:
std::string user_name = "alice";
auto data_file = user_name + ".csv";
We'll come back to this!
???
In general we'd recommend using auto quite a lot "Almost always auto"
Why?
Can't have an uninitialized variable
Add types - on RHS as constructors - when you need to ensure the type of something (is known to the reader).
#include <iostream>
#include <string>
void say_hello() {
std::cout << "Hello, world!" << std::endl;
}
int main(int argc, char* argv[]) {
std::cout << "What is your name?" << std::endl;
auto name = std::string{};
// Read from the terminal
std::cin >> name;
// Have the program greet the user by name
say_hello(name);
}
???
What I'd like you to do is change say_hello
to accept the name it
read from the terminal, create a new message saying "Hello, $NAME!"
and print it to standard output.
I've shown here how to read a string from standard input.