Skip to content
Snippets Groups Projects
Commit b567e442 authored by Marcus Mohr's avatar Marcus Mohr
Browse files

Adds more comments

parent e648ee24
Branches
Tags release/0.3.3
No related merge requests found
%% Cell type:markdown id:eb6a84a9-1411-4a9b-8cbb-c7ed29ecb9c0 tags:
# References
%% Cell type:code id:40de00aa-5b48-420d-8743-099cef5d316a tags:
``` C++17
#include <iostream>
#include <memory>
```
%% Cell type:code id:0579d3c2-3f9d-4904-8762-f1d6cdb2581d tags:
``` C++17
void check() {
int iVal = 1;
int* ptr2int = &iVal;
int** ptr2ptr = &ptr2int;
int& ref2int = iVal;
// int&& ref2ref = ref2int; // this will not work
std::cout << "iVal stores a value of ................. " << iVal << '\n';
std::cout << "iVal resides in memory at address ...... " << std::addressof( iVal ) << "\n\n";
std::cout << "ptr2int stores a value of .............. << " << ptr2int << '\n';
std::cout << "ptr2int resides in memory at address ... << " << &ptr2int << "\n\n";
std::cout << "ptr2ptr stores a value of .............. << " << ptr2ptr << '\n';
std::cout << "ptr2ptr resides in memory at address ... << " << &ptr2ptr << "\n\n";
std::cout << "ref2int stores a value of .............. << " << ref2int << '\n';
std::cout << "ref2int resides in memory at address ... << " << &ref2int << std::endl;
}
```
%% Cell type:code id:3a7034da-2d7f-4429-9853-ffd5e62eefcb tags:
``` C++17
check()
```
%% Output
iVal stores a value of ................. 1
iVal resides in memory at address ...... 0x7fffea96f2ac
ptr2int stores a value of .............. << 0x7fffea96f2ac
ptr2int resides in memory at address ... << 0x7fffea96f2a0
ptr2ptr stores a value of .............. << 0x7fffea96f2a0
ptr2ptr resides in memory at address ... << 0x7fffea96f298
ref2int stores a value of .............. << 1
ref2int resides in memory at address ... << 0x7fffea96f2ac
%% Cell type:markdown id:410de220-647d-48f0-93e5-1789d2a72300 tags:
The last two lines clearly show the difference between a pointer and a reference.
While the pointer is a variable with its own memory location, the reference is only an alias of sorts. It occupies the same place in memory and stores the same value as the object it is bound/initialised to.
%% Cell type:markdown id:7fd67f39-e7cf-473b-a316-9d093b97dc7c tags:
# Dynamic Object Creation
%% Cell type:markdown id:ff9a0e59-ce0c-4e45-a6fd-55fe94f6953e tags:
- Often we will only find out how large a problem is during execution of our program.
- Imagine e.g. that you want to run a Finite Element simulation. Typically you will use a mesh generated by an external meshing program for that. Thus, you cannot say apriorily how much memory space you will need to store the triangles/tetrahedra of that mesh.
- Thus, we need a way to allocate memory at run-time, i.e. during execution of our program.
- C++ provides the **new expression** for this.
%% Cell type:code id:8adf9d0f-35a5-4c01-b2b1-6ed24733ba00 tags:
``` C++17
// Let's check whether this works?
int main() {
int a = new int;
a = 2;
std::cout << "a stores " << a << std::endl;
}
main();
```
%% Output
input_line_10:3:7: error: cannot initialize a variable of type 'int' with an rvalue of type 'int *'
int a = new int;
^ ~~~~~~~
Interpreter Error:
%% Cell type:code id:b6955ae1-ec49-4ddc-8dc6-53d459bd6a4e tags:
``` C++17
#include <iostream>
// Corrected version
int main() {
int* a = new int;
*a = 2;
std::cout << "a stores " << a << std::endl;
std::cout << "*a stores " << *a << std::endl;
// let's check whether new initialises?
double* dPtr = new double;
std::cout << "*dPtr = " << *dPtr << std::endl;
short* sPtr = new short;
std::cout << "*sPtr = " << *sPtr << std::endl;
// no, it does not (at least not for PODs)
}
main();
```
%% Output
a stores 0x55c31b5d3ff0
*a stores 2
*dPtr = 4.65886e-310
*sPtr = 11024
%% Cell type:code id:cdb7efd5-0d40-4278-a19a-17a6d84e6dfd tags:
``` C++17
// Now let's try to dynamically allocate an array
double* array = new double[10];
for( int k = 0; k < 10; k++ ) {
std::cout << "array[" << k << "] = " << array[k] << '\n';
}
```
%% Output
array[0] = 4.65886e-310
array[1] = 0
array[2] = 0
array[3] = 0
array[4] = 4.65886e-310
array[5] = 0
array[6] = 0
array[7] = 4.65886e-310
array[8] = 4.65886e-310
array[9] = 4.65886e-310
%% Cell type:markdown id:0dc4e4be-11c2-4039-a9de-4ac522969417 tags:
### Deletion and Memory Leaks
- When we dynamically allocate something, we should also take care to delete it, once we no longer need it
- Otherwise we might generate a **memory leak**
- Same happens, if we loose the address of the allocated object
%% Cell type:code id:2a70c970-aef1-4fe3-a953-6c37fe86438d tags:
``` C++17
#include <iostream>
#include <new> // for std::nothrow
// but also comes in indirectly via iostream
#include <new> // for std::nothrow, also comes in indirectly via iostream
#include <cstdlib> // for exit(), EXIT_FAILURE
#include <limits> // for numeric_limits
double* getMem( unsigned long long n ) {
double* dPtr = nullptr;
// nothrow avoid throwing an exception if allocation fails;
// instead a nullptr is returned
dPtr = new( std::nothrow ) double[n]; //
dPtr = new( std::nothrow ) double[n];
// check, if that went smoothly
if( dPtr != nullptr ) {
std::cout << "Allocated " << sizeof(double)*n
<< " bytes at address " << dPtr << std::endl;
}
else {
std::cout << "\n *** Problem with memory allocation ***" << std::endl;
std::exit( EXIT_FAILURE );
}
// hand address back
return dPtr;
} // (1) dPtr goes out of scope now, but dynamic memory is not deleted!
```
%% Cell type:code id:e3a66e21-f10f-4a49-8663-c47cde6ca315 tags:
``` C++17
int main() {
double* arr = getMem( 100 );
std::cout << "arr starts at " << arr << std::endl;
// (1) address is still valid
arr[0] = 1.0;
delete[] arr; // delete memory block again, need [] because it's an array
// ask for too much
arr = getMem( std::numeric_limits<unsigned long long>::max() );
}
main();
```
%% Output
Allocated 800 bytes at address 0x55c319454d30
arr starts at 0x55c319454d30
Allocated 800 bytes at address 0x5603a02f5d60
arr starts at 0x5603a02f5d60
*** Problem with memory allocation ***
%% Cell type:code id:b2c0e344-1663-444d-898b-162f78af0ca2 tags:
``` C++17
#include <iostream>
int main() {
int* iPtr = nullptr;
for( unsigned int k = 1; k <= 5; ++k ) {
iPtr = new int[10];
std::cout << "40 byte block allocated at address " << iPtr << std::endl;
}
std::cout << "deleting memory block with starting address " << iPtr << std::endl;
delete[] iPtr;
}
main();
```
%% Output
40 byte block allocated at address 0x5621091b4c70
40 byte block allocated at address 0x562108fb6400
40 byte block allocated at address 0x56210913a370
40 byte block allocated at address 0x562109439530
40 byte block allocated at address 0x562108f09610
deleting memory block with starting address 0x562108f09610
40 byte block allocated at address 0x56501213e090
40 byte block allocated at address 0x5650147437c0
40 byte block allocated at address 0x56501472e010
40 byte block allocated at address 0x565014488a70
40 byte block allocated at address 0x5650140e0fe0
deleting memory block with starting address 0x5650140e0fe0
%% Cell type:code id:b9883aff-e19f-4a66-9177-da60faa124ec tags:
%% Cell type:markdown id:63030691-3c76-4ad8-8ca8-450eade595a6 tags:
In the above example we have unrecoverably **lost** 4 * 40 = 160 bytes of memory
%% Cell type:code id:69f6ee2d-5622-47bf-a92c-ae4866103428 tags:
``` C++17
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment