course notes by Kees van Kempen (ru@keesvankempen.nl)
Notes are going to be quite brief, with a sparkle of personal comments. As there only was one whole lecture, the rest is gonna be something of a summary of useful facts.
The course seems to follow Wouter Verkerke’s course on Introduction to C++ and Object Oriented Programming from 2006 with updates in 2015 called v55, although I found v60 from 2018 somewhere on a NIKHEF webpage.
I found out the hard way that copying code does not work. The rendered LaTeX pdf files sometimes changes hyphens and quotation marks to different characters depending on their place. BAH.
See notes.pdf for a pdf of these wonderful notes.
I figured out http://cpp.sh/ exists. It is really useful for quick debugging of snippets.
He asks who knows what a pointer is. “Quite a few do not.” Pointers are references to memory addresses. (A reference is something else, though.) The number of memory addresses is limited by the CPU arch. Here comes the difference between 32 and 64 bits. The length of the memory address is 32 bits vs 64 bits. 32 bit computers can often only handle some 4 GB of RAM. He asks us to familiarize ourselves with the concept, but is not giving a thorough lecture about them.
He wraps up after the 45 minutes with Walter (TA) giving some explanation about that he is writing some introductory thing and that Discord is our communication channel of choice. He and Frank encourage us to ask questions in there so other can also benefit from it. They also recommend looking at the C&CZ wiki for information about, e.g., Gitlab and ssh.
g++.const, difference between declaration and initialization, auto declaration.Type name [size] or, for multiple dimensions, Type name [size1][size2]...[sizeN].Type& name = othername&name returns the pointer to name.Type* ptr = othername*ptr returns a reference to the thing ptr points at, i.e. othername.* and & keys have ``opposite’’ effect depending on placement.Type a[size], a is a pointer to a[0].a[i] == *(a+i).malloc() and keyword new, e.g..free store.
Type* ptr = new Type allocates memory, returns pointer.delete ptr frees the memory.Type f(args):
f(Type a) gives a copy to the function;f(Type& a) gives a reference, chance affects the original;const reference: f(const Type& a) gives a reference, disallows changing a, creates no copy, so is memory efficient;f(Type* a) gives a pointer to a.int main(int argc, const char* argc[]) provides command line args.f(Type = value). Argument is then optional. Must be provided in initial declaration!using cstring = const char*; is a very suitable substitution, and feels quite natural.int a[n][m] to a function can be done as:
f(int *p)f(int p[][m])f(int (*p)[m]) (or f(int *p[m]))f(int **p).hh are of the same type as .cc code, but it is all convention.A more modern way is using #pragma once.
namespace name { /* functions, classes etc */ }using name::function; (:: = scope resolution operator)using namespace name;int main() as that is not executed.g++ -c module.cc so that module.o is created, an object file.ar binary: ar q libVeryNiceName.a module1.o module2 [...]g++ program.cc -L. -lVeryNiceName. The -l arg provides the library name that should be used in compilation. The -L. arg adds directory . to the path in which to search for libraries. So yeah, the lib prefix is required, and the name of the archive matters.valgrind is mentioned; I like it for detecting memory leaks.gdb is a debugging tool.class) and structures (struct) are used to do this.Structures
struct StructName {
// We can just define variables and functions in structures.
char var1;
int var2 = 3;
double func1 (double arg) {
return arg*2 + var2;
}
// Or only declare a function.
void banana ();
};
// This later definition allows one to use header files.
void StructName::banana() {
std::cout << "Hello i em bananna" << std::endl;
}Classes
class StructName {
// Classes allow us to limit access. Normally, the public properties
// (interface) are defined before the private (implementation) ones,
// but I copied the above example without much change.
private:
char var1;
int var2 = 3;
public:
// We can define a constructor and destructor.
StructName() { std::cout << "An instance of StructName is created!" << std::endl; };
~StructName() { std::cout << "An instance of StructName is deleted!" << std::endl; };
double func1 (double arg) {
return arg*2 + var2;
}
void banana ();
};
void StructName::banana() {
std::cout << "Hello i em bananna" << std::endl;
}this is a pointor to the instance you’re currently in.const (void print() const;). The function then cannot alter the object.
mutable (mutable int result;).Static members can be used without initialization of the class. Over all instances of the class, the member variables will be shared.
A first shot at decomposing your problem into classes.
has-a relations helps.has-a, an object can also have a uses-a relation, which often results in a pointer.constOne of the most ubiquitous qualifier in C++ is const. A variable can be declared constant, a pointer can be declared constant, a reference can be declared constant. We can also declare constant what a variable points to. We can also declare that a class cannot be changed by some member function, thus also using constant. Let’s see some examples. Major inspiration is stolen from http://duramecho.com/ComputerInformation/WhyHowCppConst.html.
// A constant value
const int var1 = 69;
// A variable pointer to a constant value
const int* var2 = 69;
int const* var3 = 69;
(int const)* var4 = 69;
(int const) * var5 = 69;
// A pointer to a constant address with a variable value
int* const var6 = 69;
(int*) const var7 = 69;
// A constant address to a constant variable
int const* const var8 = 69;
(int const)* const var9 = 69;
const (int const)* var10 = 69;And a completely working example:
#include <iostream>
int main()
{
int* temp = new int;
*temp = 70;
// A constant pointer to a variable value
int* const var1 = temp;
// A constant address to a constant variable
int const* const var2 = temp;
const int* const var3 = temp;
// A constant value
const int var4 = 69;
// A variable pointer to a constant value
const int* var5;
int const* var6;
std::cout << *var2;
*temp = 71;
std::cout << *var2;
// The following is illegal
//*var2 = 90;
// But we can alter temp, and thus alter the value of var2
std::cout << *var2;
std::cout << std::endl << temp << std::endl << var2;
}I mostly like the conclusion of said website:
Basically ‘const’ applies to whatever is on its immediate left (other than if there is nothing there in which case it applies to whatever is its immediate right).