2.Modern C++ and git
28 May 2020 | Modern C++
Outline
- Variables and baisc types
- built-in types
- Strings
- Vector and array
- Control structures
- If statement
- Switch statement
- Loops
Declaring variables
Variable declaration always follows pattern:
-
[ = ];
- Every variable has a type
- Variables cannot change their type
- Always initialize variables if you can
int sad_uninitialized_var;
bool initializing_is_good = true;
Naming variables
- Name must start with a letter
- Give variables meaningful names
- Don’t be afraid to use longer names
- Don’t include type in the name
- Don’t use negation in the name
- GOOGLE-STYLE name variables in snake_case all lowercase, underscores separate words
- C++ is case sensitive:
- some_var is different from some_Var
Built-in types
“Out of the box” types in C++:
Operations on arithmetic types
- All character, integer and floating point types are arithmetic
- Arithmetic operations: +, -, * , /
- Comparisons <, >, <=, >=, == return bool
- a += 1 ⇔ a = a + 1, same for -=, * =, /=, etc
- Avoid == for floating point types
Some additional operations
- Boolean variables have logical operations
-
or:
, and: &&, not: !
bool is_happy = (!is_hungry && is_warm) || is_rich
- Additional operations on integer variables:
- / is integer division: i.e. 7 / 3 == 2
- % is modulo division: i.e. 7 / 3 == 1
- Increment operator: a++ ⇔ ++a ⇔ a += 1
- Decrement operator: a– ⇔ –a ⇔ a -= 1
- Do not use de- increment operators within another expression, i.e. a = (a++) + ++b
Strings
- #include
to use std::string
- Concatenate strings with +
- Check if str is empty with str.empty()
- Works out of the box with I/O streams
#include <iostream>
#include <string>
int main() {
std::string hello = "Hello";
std::cout << "Type your name:" << std::endl;
std::string name = ""; // Init empty.
std::cin >> name; // Read name.
std::cout << hello + ", " + name + "!" << std::endl;
return 0;
}
Use std::array for fixed size collections of items(allocate stack memory as static programming)
- #include
to use std::array
- Store a collection of items of same type
- Create from data:
- array<float, 3> arr = {1.0f, 2.0f, 3.0f};
- Access items with arr[i]
- indexing starts with 0
- Number of stored items: arr.size()
- Useful access aliases:
- First item: arr.front() == arr[0]
- Last item: arr.back() == arr[arr.size() - 1]
Use std::vector when number of items is unknown before-wise(allocated heap memory as dynamic programming)
- #include
to use std::vector
- Vector is implemented as a dynamic table
- Access stored items just like in std::array
- Remove all elements: vec.clear()
- Add a new item in one of two ways:
- vec.emplace_back(value) [preferred, c++11]
- vec.push_back(value) [historically better known]
- Use it! It is fast and flexible!
- Consider it to be a default container to store collections of items of any same type
Optimize vector resizing
- Many push_back/emplace_back operations force vector to change its size many times
- reserve(n) ensures that the vector has enough memory to store n items
- The parameter n can even be approximate
- This is a very important optimization
std::vector <std::string > vec;
const int kIterNum = 100;
// Always call reserve when you know the size.
for (int i = 0; i < kIterNum; ++i) {
vec.emplace_back("hello");
}
Example Vector
#include <string >
#include <vector >
#include <iostream >
using namespace std;
int main() {
vector <int> numbers = {1, 2, 3};
vector <string > names = {"Igor", "Cyrill"};
names.push_back("another_string");
cout << "First name: " << names.front() << endl;
cout << "Last number: " << numbers.back() << endl;
return 0;
}
Variables live in scopes
- There is a single global scope
- Local scopes start with { and ends with }
- All variables belong to the scope where they have been declared
- All variables die in the end of their scope
- This is the core of C++ memory system
int main()// Start of main scope.
{
float some_float = 13.13f; // Create variable.
{
// New inner scope
auto another_float = some_float; // Copy variable.
} // another_float dies
return 0;
}// some_float dies.
Any variable can be const
- Use const to declare a constant
- The compiler will guard it from any changes
- Keyword const can be used with any type
- GOOGLE-STYLE name constants in CamelCase starting with a small letter k:
- const float kImportantFloat = 20.0f;
- const int kSomeInt = 20;
- const std::string kHello = “hello”;
- const is part of type:
- variable kSomeInt has type const int
- Tip: declare everything const unless it must be changed
References to variables
- We can create a reference to any variable
- Use & to state that a variable is a reference
- float& ref = original_variable;
- std::string& hello_ref = hello;
- Reference is part of type: variable ref has type float&
- Whatever happens to a reference happens to the variable and vice versa
- Yields performance gain as references avoid copying data
Const with references
- References are fast but reduce control
- To avoid unwanted changes use const
- const float& ref = original_variable;
- const std::string& hello_ref = hello;
#include <iostream >
using namespace std;
int main() {
int num = 42; // Name has to fit on slides
int& ref = num;
const int& kRef = num;
ref = 0;
cout << ref << " " << num << " " << kRef << endl; // output 0 0 0
num = 42;
cout << ref << " " << num << " " << kRef << endl; // output 42 42 42
return 0;
}
If statement
if (STATEMENT) {
// This is executed if STATEMENT == true
} else if (OTHER_STATEMENT) {
// This is executed if:
// (STATEMENT == false) && (OTHER_STATEMENT == true)
} else {
// This is executed if neither is true
}
- Used to conditionally execute code
- All the else cases can be omitted if needed
- STATEMENT can be any boolean expression
Switch Statement
switch(STATEMENT) {
case CONST_1:
// This runs if STATEMENT == CONST_1.
break;
case CONST_2:
// This runs if STATEMENT == CONST_2.
break;
default:
// This runs if no other options worked.
}
- Used to conditionally execute code
- Can have many case statements
- break exits the switch block
- STATEMENT usually returns int or enum value
While loop
while (STATEMENT) {
// Loop while STATEMENT == true.
}
Example while loop:
bool condition = true;
while (condition) {
condition = /* Magically update condition. * /
}
- Usually used when the exact number of iterations is unknown before-wise
- Easy to form an endless loop by mistake
For loop
for (INITIAL_CONDITION; END_CONDITION; INCREMENT) {
// This happens until END_CONDITION == false
}
Example for Loop
for (int i = 0; i < COUNT; ++i) {
// This happens COUNT times.
}
- In C++ for loops are very fast. Use them!
- Less flexible than while but less error-prone
- Use for when number of iterations is fixed and while otherwise
Range for loop
- Iterating over a standard containers like array or vector has simpler syntax
- Avoid mistakes with indices
- Show intent with the syntax
- Has been added in C++11
for (const auto& value : container) {
// This happens for each value in the container.
}
Exit loops and iterations
- We have control over loop iterations
- Use break to exit the loop
- Use continue to skip to next iteration
while (true) {
int i = /* Magically get new int. *
if (i % 2 == 0) {
cerr << i << endl;
}
else{
break;
}
}
Git
- Free software for distributed version control
- synchronizes local and remote files
- stores a history of all changes
What is synchronized?
- Local files on a computer
- Remote Files in the repository
- We are using a Gitlab server
Typical workflow
Cloning a repository:
- git clone
In :
- Change files
- git add
- git commit -am ‘descriptive message’
- git push origin master
Reference
https://www.ipb.uni-bonn.de/teaching/modern-cpp/
Cpp Core Guidelines:
https://github.com/isocpp/CppCoreGuidelines
Git guide:
http://rogerdudler.github.io/git-guide/
C++ Tutorial:
http://www.cplusplus.com/doc/tutorial/
Book: Code Complete 2 by Steve McConnell
Outline
- Variables and baisc types
- built-in types
- Strings
- Vector and array
- Control structures
- If statement
- Switch statement
- Loops
Declaring variables
Variable declaration always follows pattern:
-
[ = ]; - Every variable has a type
- Variables cannot change their type
- Always initialize variables if you can
int sad_uninitialized_var;
bool initializing_is_good = true;
Naming variables
- Name must start with a letter
- Give variables meaningful names
- Don’t be afraid to use longer names
- Don’t include type in the name
- Don’t use negation in the name
- GOOGLE-STYLE name variables in snake_case all lowercase, underscores separate words
- C++ is case sensitive:
- some_var is different from some_Var
Built-in types
“Out of the box” types in C++:
Operations on arithmetic types
- All character, integer and floating point types are arithmetic
- Arithmetic operations: +, -, * , /
- Comparisons <, >, <=, >=, == return bool
- a += 1 ⇔ a = a + 1, same for -=, * =, /=, etc
- Avoid == for floating point types
Some additional operations
- Boolean variables have logical operations
-
or: , and: &&, not: !
-
bool is_happy = (!is_hungry && is_warm) || is_rich
- Additional operations on integer variables:
- / is integer division: i.e. 7 / 3 == 2
- % is modulo division: i.e. 7 / 3 == 1
- Increment operator: a++ ⇔ ++a ⇔ a += 1
- Decrement operator: a– ⇔ –a ⇔ a -= 1
- Do not use de- increment operators within another expression, i.e. a = (a++) + ++b
Strings
- #include
to use std::string - Concatenate strings with +
- Check if str is empty with str.empty()
- Works out of the box with I/O streams
#include <iostream>
#include <string>
int main() {
std::string hello = "Hello";
std::cout << "Type your name:" << std::endl;
std::string name = ""; // Init empty.
std::cin >> name; // Read name.
std::cout << hello + ", " + name + "!" << std::endl;
return 0;
}
Use std::array for fixed size collections of items(allocate stack memory as static programming)
- #include
to use std::array - Store a collection of items of same type
- Create from data:
- array<float, 3> arr = {1.0f, 2.0f, 3.0f};
- Access items with arr[i]
- indexing starts with 0
- Number of stored items: arr.size()
- Useful access aliases:
- First item: arr.front() == arr[0]
- Last item: arr.back() == arr[arr.size() - 1]
Use std::vector when number of items is unknown before-wise(allocated heap memory as dynamic programming)
- #include
to use std::vector - Vector is implemented as a dynamic table
- Access stored items just like in std::array
- Remove all elements: vec.clear()
- Add a new item in one of two ways:
- vec.emplace_back(value) [preferred, c++11]
- vec.push_back(value) [historically better known]
- Use it! It is fast and flexible!
- Consider it to be a default container to store collections of items of any same type
Optimize vector resizing
- Many push_back/emplace_back operations force vector to change its size many times
- reserve(n) ensures that the vector has enough memory to store n items
- The parameter n can even be approximate
- This is a very important optimization
std::vector <std::string > vec;
const int kIterNum = 100;
// Always call reserve when you know the size.
for (int i = 0; i < kIterNum; ++i) {
vec.emplace_back("hello");
}
Example Vector
#include <string >
#include <vector >
#include <iostream >
using namespace std;
int main() {
vector <int> numbers = {1, 2, 3};
vector <string > names = {"Igor", "Cyrill"};
names.push_back("another_string");
cout << "First name: " << names.front() << endl;
cout << "Last number: " << numbers.back() << endl;
return 0;
}
Variables live in scopes
- There is a single global scope
- Local scopes start with { and ends with }
- All variables belong to the scope where they have been declared
- All variables die in the end of their scope
- This is the core of C++ memory system
int main()// Start of main scope.
{
float some_float = 13.13f; // Create variable.
{
// New inner scope
auto another_float = some_float; // Copy variable.
} // another_float dies
return 0;
}// some_float dies.
Any variable can be const
- Use const to declare a constant
- The compiler will guard it from any changes
- Keyword const can be used with any type
- GOOGLE-STYLE name constants in CamelCase starting with a small letter k:
- const float kImportantFloat = 20.0f;
- const int kSomeInt = 20;
- const std::string kHello = “hello”;
- const is part of type:
- variable kSomeInt has type const int
- Tip: declare everything const unless it must be changed
References to variables
- We can create a reference to any variable
- Use & to state that a variable is a reference
- float& ref = original_variable;
- std::string& hello_ref = hello;
- Reference is part of type: variable ref has type float&
- Whatever happens to a reference happens to the variable and vice versa
- Yields performance gain as references avoid copying data
Const with references
- References are fast but reduce control
- To avoid unwanted changes use const
- const float& ref = original_variable;
- const std::string& hello_ref = hello;
#include <iostream >
using namespace std;
int main() {
int num = 42; // Name has to fit on slides
int& ref = num;
const int& kRef = num;
ref = 0;
cout << ref << " " << num << " " << kRef << endl; // output 0 0 0
num = 42;
cout << ref << " " << num << " " << kRef << endl; // output 42 42 42
return 0;
}
If statement
if (STATEMENT) {
// This is executed if STATEMENT == true
} else if (OTHER_STATEMENT) {
// This is executed if:
// (STATEMENT == false) && (OTHER_STATEMENT == true)
} else {
// This is executed if neither is true
}
- Used to conditionally execute code
- All the else cases can be omitted if needed
- STATEMENT can be any boolean expression
Switch Statement
switch(STATEMENT) {
case CONST_1:
// This runs if STATEMENT == CONST_1.
break;
case CONST_2:
// This runs if STATEMENT == CONST_2.
break;
default:
// This runs if no other options worked.
}
- Used to conditionally execute code
- Can have many case statements
- break exits the switch block
- STATEMENT usually returns int or enum value
While loop
while (STATEMENT) {
// Loop while STATEMENT == true.
}
Example while loop:
bool condition = true;
while (condition) {
condition = /* Magically update condition. * /
}
- Usually used when the exact number of iterations is unknown before-wise
- Easy to form an endless loop by mistake
For loop
for (INITIAL_CONDITION; END_CONDITION; INCREMENT) {
// This happens until END_CONDITION == false
}
Example for Loop
for (int i = 0; i < COUNT; ++i) {
// This happens COUNT times.
}
- In C++ for loops are very fast. Use them!
- Less flexible than while but less error-prone
- Use for when number of iterations is fixed and while otherwise
Range for loop
- Iterating over a standard containers like array or vector has simpler syntax
- Avoid mistakes with indices
- Show intent with the syntax
- Has been added in C++11
for (const auto& value : container) {
// This happens for each value in the container.
}
Exit loops and iterations
- We have control over loop iterations
- Use break to exit the loop
- Use continue to skip to next iteration
while (true) {
int i = /* Magically get new int. *
if (i % 2 == 0) {
cerr << i << endl;
}
else{
break;
}
}
Git
- Free software for distributed version control
- synchronizes local and remote files
- stores a history of all changes
What is synchronized?
- Local files on a computer
- Remote Files in the repository
- We are using a Gitlab server
Typical workflow
Cloning a repository:
- git clone
In : - Change files
- git add
- git commit -am ‘descriptive message’
- git push origin master
Reference
https://www.ipb.uni-bonn.de/teaching/modern-cpp/
Cpp Core Guidelines: https://github.com/isocpp/CppCoreGuidelines
Git guide: http://rogerdudler.github.io/git-guide/
C++ Tutorial: http://www.cplusplus.com/doc/tutorial/
Book: Code Complete 2 by Steve McConnell
Comments