Skip to content

Commit 4a50a5f

Browse files
authored
add tutorial/cpp (acs-pa#5)
1 parent eb9ebf3 commit 4a50a5f

30 files changed

+785
-0
lines changed

tutorial/cpp/cpp.md

+369
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
# C++ Tutorial
2+
3+
Maintainers:
4+
* Radu Nichita (radunichita99@gmail.com)
5+
* Darius Neatu (neatudarius@gmail.com)
6+
7+
## TLDR
8+
A short summary for what you need / should use at PA can be found at [PA C++: TLDR](tldr.md).
9+
10+
## Docs
11+
12+
Links:
13+
* [en.cppreference.com](https://en.cppreference.com): main C++ documentation
14+
* [C++ reference](https://en.cppreference.com/w/cpp): C++ documentation
15+
* [cppreference/algorithm](https://en.cppreference.com/w/cpp/algorithm): STL algorithms docs
16+
* [cppreference/container](https://en.cppreference.com/w/cpp/container): STL containers docs
17+
* [C reference](https://en.cppreference.com/w/c): C API also available in C++
18+
19+
C++ has multiple standards (see [cppreference/history](https://en.cppreference.com/w/cpp/language/history)). In this tutorial the C++17 standard (g++ flag: `-std=c++17`) is assumed. The laboratory skeletons use C++17 and we strongly encourage to also do it for homeworks / projects.
20+
21+
## C++ basics
22+
23+
* C++ is a high-level language, sometimes called a superset of C.
24+
* It supports imperative, object-oriented and generic programming.
25+
26+
### Hello Gigel in C++
27+
28+
```cpp
29+
#include <iostream>
30+
31+
int main() {
32+
int x;
33+
std::cin >> x;
34+
std::cout << "Hello, Gigel! I got " << x << " from the PA team!"
35+
return 0;
36+
}
37+
```
38+
39+
Explanations:
40+
* `io`:
41+
* The standard C++ input/output library is `<iostream>`.
42+
* Streams:
43+
* `std::cin`: reading from `STDIN` with operator `>>`
44+
* `std::cout`: writing to `STDOUT` with operator `<<`
45+
* `std::cerr`: writing to `STDERR` with operator `<<`
46+
* Please check `io.md` for file operations.
47+
* `namespace`
48+
* >Namespaces provide a method for preventing name conflicts in large projects. ([cppreference/namespace](https://en.cppreference.com/w/cpp/language/namespace))
49+
* A namespace groups variables, types and functions together.
50+
51+
52+
* To compile any C++ program, use
53+
```bash
54+
# compile
55+
g++ -Wall -Wextra -std=c++17 <source_name> -o <executable_name>
56+
```
57+
58+
* To run any compiled C++ program, use
59+
```bash
60+
./<executable_name>
61+
```
62+
63+
---
64+
Notes for `PA-only`:
65+
* Compiler flags:
66+
* always use `-std=c++17`
67+
* never use optimizations flags (the purpose of this class is to find the solution with the best complexity)
68+
* It's `encouraged` to use `using namespace std` ([stackoverflow/using-namespace-std](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)) instead of specifing `std::` everywhere. This tutorial we'll use the second approach.
69+
* Always use the provided skeleton for the laboratory.
70+
71+
---
72+
73+
74+
### C vs C++
75+
* **struct in C** vs **struct in C++**
76+
* > "A struct in the C programming language is a composite data type declaration that defines a physically grouped list of variables under one name in a block of memory, allowing the different variables to be accessed via a single pointer or by the struct declared name which returns the same address. The struct data type can contain other data types so is used for mixed-data-type records such as a hard-drive directory entry (file length, name, extension, physical address, etc.), or other mixed-type records (name, address, telephone, balance, etc.)." ([wikipedia/struct (C programming language)](https://en.wikipedia.org/wiki/Struct_(C_programming_language)))
77+
* > "A class in C++ is a user-defined type or data structure declared with keywords struct or class that has data and functions (also called member variables and member functions or methods) as its members whose access is governed by the three access specifiers private, protected or public." ([wikpedia/C++ classes](https://en.wikipedia.org/wiki/C%2B%2B_classes)).
78+
79+
80+
* Basic example of C struct conversion to C++ struct
81+
82+
In C we can define a struct and some functions which can process this type.
83+
84+
```cpp
85+
// C struct
86+
typedef struct {
87+
double re;
88+
double im;
89+
} complex_t;
90+
91+
void print_complex(complet_t c)
92+
{
93+
printf("%lf + %lf\n", c.re, c.im);
94+
}
95+
96+
int main()
97+
{
98+
complex_t c = {1, 2}; // 1 + 2i
99+
print_complex(c);
100+
return 0;
101+
}
102+
```
103+
104+
In C++ we can move the functions which process the new type inside the struct.
105+
```cpp
106+
// C++ struct
107+
struct Complex {
108+
double re, im;
109+
110+
void print() {
111+
// the im and re members for the current Complex object are accessed
112+
std::cout << re << "+" << im << "i" << "\n";
113+
}
114+
};
115+
116+
int main()
117+
{
118+
Complex c;
119+
c.re = 1;
120+
c.im = 2;
121+
c.print();
122+
return 0;
123+
}
124+
```
125+
126+
* **access specifiers**: struct vs class in C++
127+
128+
Members (data and methods) can be:
129+
* **public** - accessible from anywhere
130+
* **private** - only accessible in the class
131+
* **protected** - only accessible on the inheritance chain (not relevant for PA)
132+
133+
Notes:
134+
* **struct** members are **public** by default.
135+
* **class** members are **private** by default.
136+
137+
```cpp
138+
#include <iostream>
139+
140+
class Gigel {
141+
int x = 100; // private because is in a class;
142+
// if Gigel was struct, x was public.
143+
public:
144+
void show() {
145+
std::cout << "x is " << x << "\n";
146+
}
147+
};
148+
149+
int main() {
150+
Gigel g;
151+
g.show(); // print "x is 100"
152+
return 0;
153+
}
154+
```
155+
156+
### Constructors and destructors
157+
* [cppreference/constructor](https://en.cppreference.com/w/cpp/language/constructor)
158+
* [cppreference/destructor](https://en.cppreference.com/w/cpp/language/destructor)
159+
160+
#### Constructor
161+
A constructor is **a special method** that is **automatically** called `when` an object of a class is created.
162+
* The constructor has the same name as the class name.
163+
* The constructor has **no return type**.
164+
* The constructor can take 0 or more parameters (just like regular functions).
165+
* If no constructor is defined, the compiler "creates" one, which does nothing and it is called **default constructor**.
166+
* A class can have **multiple** constructors with different parameters.
167+
168+
```cpp
169+
#include <iostream>
170+
171+
class Gigel {
172+
public:
173+
Gigel() {
174+
std::cout << "Gigel()\n";
175+
}
176+
177+
Gigel(int x) {
178+
std::cout << "Gigel(" << x << ")\n";
179+
}
180+
};
181+
182+
int main() {
183+
Gigel g; // print "Gigel()"
184+
Gigel g2{}; // print "Gigel()"
185+
Gigel g3{10}; // print "Gigel(10)"
186+
Gigel g4(5); // print "Gigel(5)"
187+
}
188+
```
189+
Note: In C++ we call the constructor for a class `Gigel` by using `Gigel()` or `Gigel{}`. It's strongly recommended to only use the `{}` notation in order to avoid some weird compile error (see [Most vexing parse C++](https://en.wikipedia.org/wiki/Most_vexing_parse)).
190+
191+
#### Destructor
192+
A destructor is a **special method** that is called `when` the lifetime of an object ends. The purpose
193+
of the destructor is to free the resources that the object may have acquired during its lifetime.
194+
195+
### Dynamic allocation: C vs C++
196+
* **new / malloc** are used to dynamically allocate memory. A difference is that **new** does call the
197+
constructor and **malloc** does not.
198+
199+
* **delete / free** are used to free the allocate memory. A difference is that **delete** does call the
200+
destructor and **free** does not.
201+
202+
Note: The usage of malloc / free in C++ is considered unsafe and it's forbidden. The new / delete functions should be used instead.
203+
204+
---
205+
206+
During the PA labs you won't used dynamic allocation, because we want to keep the things as simple as possible:
207+
* a single call to `new / delete` will be made in the `main()` function - the skeleton already has the implementation for `main()`.
208+
* when solving the tasks you must use containers from STL (e.g. `std::vector`) which allocate and automatically deallocate memory.
209+
210+
---
211+
212+
### auto keyword
213+
* > "For variables, specifies that the type of the variable that is being declared will be automatically deduced from its initializer. For functions, specifies that the return type will be deduced from its return statements." ([cppreference/auto](https://en.cppreference.com/w/cpp/language/auto))
214+
215+
```cpp
216+
#include <iostream>
217+
218+
// the return type for square() is automaticaly deduce to double because the returned value
219+
// (x * x) is a double
220+
auto square(double x) {
221+
return x * x;
222+
}
223+
224+
int main() {
225+
auto x = 10.0; // the type of x is automatically deduced to double because 10.0 it's a double
226+
std::cout << square(x) << "\n";
227+
return 0;
228+
}
229+
```
230+
231+
### References in C++
232+
* A pointer is a **variable** that holds a memory address (e.g. `0xCAFEBABE` or the address of another variable).
233+
* Both C and C++ have pointers. Additionally, C++ has references.
234+
* A reference is **an alias** for **an already existing variable**. Once a reference is initialized to a variable, it cannot be changed to refer to another variable (hence, a reference is similar to a fixed pointer). The referenced variable can be changed using the reference.
235+
236+
```cpp
237+
#include <iostream>
238+
239+
// C: if we want to change x in function foo, we need to pass using a pointer
240+
void modify_c(int *x) {
241+
*x = 123;
242+
}
243+
// call example:
244+
// int x;
245+
// modify_c(&x);
246+
247+
// C++: we can pass by reference
248+
void modify_cpp(int &x) {
249+
x = 123; // x it's a reference to the "x" variable from main
250+
}
251+
252+
int main() {
253+
int x = 0;
254+
modify_cpp(x);
255+
std::cout << x << "\n"; // print 123 because x was changed to 123 in modify_cpp()
256+
return 0;
257+
}
258+
```
259+
260+
### Templates
261+
In C++, templates allow to pass to functions/classes the data type as parameter, so there is no need to write the same code for different data types.
262+
263+
#### template functions
264+
A function which may have generic parameter(s) or return type.
265+
* generic return type
266+
267+
```cpp
268+
template<typename T>
269+
T func(...) {
270+
// ...
271+
return T{...};
272+
}
273+
// usage example for int
274+
int x = func<int>();
275+
276+
// usage example for struct Gigel
277+
Gigel gigel = func<Gigel>();
278+
// or
279+
auto gigel = func<Gigel>();
280+
```
281+
282+
* generic parameter type(s)
283+
```cpp
284+
// example of template function
285+
// which has 2 parameters of type T (reference to T)
286+
template<typename T>
287+
void func(T& a, T&b) {
288+
// ...
289+
}
290+
// usage example for int
291+
func<int>(123, 456);
292+
// example of template function
293+
// which has 2 parameters of type K and V
294+
template<typename K, typename B>
295+
void func(K &a, V &v) {
296+
// ...
297+
}
298+
// usage example for int and struct Gigel
299+
func<int, Gigel>(123, Gigel{});
300+
```
301+
302+
```cpp
303+
#include <iostream>
304+
305+
// generic maximum function: a and b have the same template type T
306+
template <typename T>
307+
T my_max (T a, T b) {
308+
return (a > b ? a : b);
309+
}
310+
311+
int main() {
312+
// usage example for T = int
313+
std::cout << my_max<int>(2, 3) << "\n";
314+
// or let to compile to automatically determine the T type from the passed values
315+
std::cout << my_max(2, 3) << "\n";
316+
317+
// usage example for T = double
318+
std::cout << my_max(3.4, 5.6) << "\n";
319+
320+
// usage example for T = char
321+
std::cout << my_max('a', 'b') << "\n";
322+
return 0;
323+
}
324+
```
325+
326+
### template classes
327+
Classes which depend of a template type `T` (e.g. a struct with a `T` member which can be an `int` or ` double`).
328+
Consider the next simple class which has an `int` member;
329+
330+
```cpp
331+
class MyClass {
332+
public:
333+
int get_member() { return member; }
334+
void set_member(int new_value) { member = new_value; }
335+
private:
336+
int member;
337+
};
338+
```
339+
340+
If we want to make a similar class with a member `double` we would copy the class and replace `int` with `double`. We also need to rename the class. If instead we use a template class, we need to:
341+
342+
* replace `int` with `T` (a generic type)
343+
* declare that the class is template (using ```cpp template<typename T>``` before class MyClass)
344+
345+
```cpp
346+
template<typename T>
347+
class MyClass {
348+
public:
349+
T get_member() { return member; }
350+
void set_member(T new_value) { member = new_value; }
351+
private:
352+
T member;
353+
};
354+
355+
// usage example for int
356+
MyClass<int> mc_int;
357+
mc_int.set_member(123); // set an int value
358+
std::cout << mc_int.get_member() << "\n"; // print 123
359+
360+
// usage example for class Gigel
361+
MyClass<Gigel> mc_gigel;
362+
mc_gigel.set_member(Gigel{}); // set a Gigel value
363+
std::cout << mc_gigel.get_member() << "\n"; // print the Gigel value
364+
```
365+
366+
## STL
367+
C++ provides implementation for various data types and algorithms which are grouped into the `STL` (the Standard Template Library - generic / template functions and classes).
368+
369+
Please continue the tutorial from the `STL` tree.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# algorithms
2+
3+
TODO
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# containers
2+
3+
Various STL containers.
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../utils/Makefile

0 commit comments

Comments
 (0)