Merge branch 'integration' into angular-value-accessor

This commit is contained in:
Corbin Crutchley
2020-06-07 15:17:42 -07:00
9 changed files with 193 additions and 10 deletions

View File

@@ -0,0 +1,150 @@
---
{
title: 'Pointers and References in C/C++',
description: 'An overview of how pointers and references function in C/C++',
published: '2020-06-02T09:40:00.000Z',
authors: ['seanmiller'],
tags: ['computer science', 'cpp'],
attached: [],
license: 'cc-by-nc-nd-4'
}
---
Every new C/C++ programmer will eventually reach the point at which they are forced to work with pointers and will undoubtedly realize that they extremely dislike using them because they are a little complex. Today, we'll be looking at what pointers are, deconstructing their usage, and hopefully, making the usage of pointers easier to grok.
# What is a Pointer? {#what-is-a-pointer}
A pointer is simply a variable or object that instead of holding a value, holds a memory address to another spot in memory. You will commonly see a pointer being most recognizable by their declaration including the **\*** operator, also known as the **dereference operator**. This operator is called the dereference operator because when you try to access the value that the pointer is referencing, you have to use the **\*** operator to "de-reference" the value. Which is just a fancy way of saying, "go to that reference".
Here's an example:
```cpp
// Defines int variable num
int num = 12;
// Declares pointer p
// Ignore the '&' symbol here, we'll discuss that next
int *p = #
// Prints out the memory address that p is pointing to
cout << p << endl;
// Prints out the memory address of num
// Again ignore the '&' symbol here, we'll discuss that next
cout << &num << endl;
// Dereferences the pointer p
cout << *p << endl;
// Prints out the value num
cout << num << endl;
```
This should print out something like...
```
0xffffcc14
0xffffcc14
12
12
```
As you can see, the pointer p holds the memory address of num, and when you use the dereference operator, the value at num is printed out.
Pointers can also get a lot more complex and must be used in certain situations. For example, if you put an object on the heap (Check out my article on Virtual Memory to learn more about heap memory) then you will have to use a pointer because you can't access the heap directly. So, instead of having a pointer to an address on the stack, it will point to an address on the heap. You might even find yourself using double or triple pointers as you get more used to them.
# What is a Reference? {#what-is-a-reference}
In simple terms, a reference is simply the address of whatever you're passing. The difference between a pointer and a reference lies in the fact that a reference is simply the **address** to where a value is being stored and a pointer is simply a variable that has it's own address as well as the address its pointing to. I like to consider the **&** operator the "reference operator" even though I'm pretty sure that's not actually what it is called. I used this operator in the last example, and it's pretty straightforward.
```cpp
int num = 12;
int *val = &num;
int **doublePointer = &val;
cout << "Address of num: " << &num << endl;
cout << "Value of val" << val << endl;
// Pointers have memory addresses too!
cout << "Address of val" << &val << endl;
// Prints out every phase of the double pointer
cout << &doublePointer << " : " << doublePointer << " : ";
cout << *doublePointer << " : " << **doublePointer << endl;
```
The output will look something like this...
```
Address of num: 0xffffcc1c
Value of val: 0xffffcc1c
Address of val: 0xffffcc10
0xffffcc08 : 0xffffcc10 : 0xffffcc1c : 12
```
As you can see, all the **&** operator does is gives you the memory address at its specific spot in memory. I also included a small example of a double-pointer which just contains one more layer of abstraction then a single pointer. You can see how the memory addresses line up in the output.
Heres what this looks like in memory with more easily understandable addresses in a “0x…” format.
**![Memory Example](./memory.png)**
# Pass by Reference vs. Pass by Value {#passing}
This is another more complex topic that we as programmers need to be aware of in almost all languages - even languages without pointers. The idea of the two all stems from functions, sometimes called methods, and their parameters. Whenever you pass something into a function, does the original variable/object that is passed in get updated inside as well as outside the function, or is it hyperlocal and it just creates a copy of the original parameter? "Pass by reference" refers to when the parameter is changed both within the function and outside of it. "Pass by value" refers to when the parameters are merely a copy and have their own memory address, only being updated inside of the function.
The primary difference between the two is what happens when you change values. If you pass by reference and update the property, it will update the original variable that was passed as well. However, if you pass by value and update it in the function, it will not impact the original variable.
The neat part of C++ is that you can control whether something is passed by reference or passed by value, but rather than try and explain it further let's look at an example.
```cpp
// Pass by reference
void passByReference(int &num) {
num += 2;
}
// Pass by value
void passByValue(int num) {
num += 2;
}
int main() {
int num1 = 0;
int num2 = 0;
cout << "Original values: " << num << endl;
// call passByReference()
passByReference(num1);
cout << "After passing by reference: " << num << endl;
// call passByValue()
passByValue(num2);
cout << "After passing by value: " << num << endl;
}
```
The output of this looks like...
```
Original values: 0
After passing by reference: 2
After passing by value: 0
```
As you can see, when passed by reference the local value is changed but when it is passed by value it is not even though they both perform the same operation. In languages outside of C++ — like Java for example — doesn't give you control of whether you pass by value or reference; Some types of objects or variables are passed by reference and some aren't. For example, Java collections are passed by reference, but all other variables and objects are passed by value.
This gets confusing after a while if you're not paying attention to your outputs. In fact, Python gets even more confusing, but that's a topic for another day; be sure to sign up for our newsletter to see when that lands 😉
# Review/Conclusion {#conclusion}
Pointers and References are extremely important in your day to day work in languages like C/C++. C++ gives you a lot of manual control with the most common being memory. Knowing how each one of your pointers or variables are stored will help you write code faster and more efficiently. Knowing also how parameters are passed to your functions as well as how they are updated, will make your life **so** much easier.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -14,11 +14,11 @@ Memory in your standard computer works in a much more abstract and complex way t
# Virtual Memory {#virtual-memory}
Operating systems (OS) are the ones in control of all of the physical memory in your computer. This is a safeguard to make sure that memory is being allocated fairly to all processes, the way this is done by a concept called **Virtual Memory**. As the name suggests, it means that it's shrouding the physical memory in hardware with seemingly infinite storage (in reality, you're limited by various elements of your hardware, but the amount of memory you can assign to virtual memory is typically orders of magnitude higher than the amount you can store in physical memory) for each process that is created. This is accomplished by using more than just your main memory in the case that if you need more storage, then the OS can also store it on your hard drive or SSD. Even though it may seem like a slower alternative, it allows much more freedom for processes without wrecking your computer.
Operating systems (OS) are the ones in control of all of the physical memory in your computer. This is a safeguard to make sure that memory is being allocated fairly to all processes. The way this is done is by a concept called **Virtual Memory**. As the name suggests, it means that it's shrouding the physical memory in hardware with seemingly infinite storage (in reality, you're limited by various elements of your hardware, but the amount of memory you can assign to virtual memory is typically orders of magnitude higher than the amount you can store in physical memory) for each process that is created. This is accomplished by using more than just your main memory in the case that if you need more storage, then the OS can also store it on your hard drive or SSD. Even though it may seem like a slower alternative, it allows much more freedom for processes without wrecking your computer.
![Representation of how virtual memory works](./virtual_memory.svg)
Virtual Memory uses what are called **page tables** that then point to a memory map that will then finally point to either your physical memory or something like an HDD. It works like a cache where each entry in a page table is only used when absolutely necessary. Whenever a process comes in it only stores the pages that the OS thinks the process will need in main memory while the rest stay behind. This reduces the amount of memory that is taken up as well as speeding up the overall time it would take to complete a process.
Virtual Memory uses what are called **page tables** that point to a memory map which will then finally point to either your physical memory or something like an HDD. It works like a cache where each entry in a page table is only used when absolutely necessary. Whenever a process comes in it only stores the "pages" that the OS thinks the process will need in main memory while the rest stay behind. This reduces the amount of memory that is taken up as well as speeding up the overall time it would take to complete a process.
## What Virtual Memory looks like in C/C++ {#virtual-memory-cpp}
@@ -102,7 +102,7 @@ int main() {
Just so we understand what is going on here, I created a global vector pointer that I did not define. Therefore it is just on the stack represented as a '0'. When example1() is called it allocates memory for vec on the heap and instantiates a vector with all zeros. You can access the vector using the memory address on the stack. When I print out just "vec" it will print out the memory address of the location on the heap where it is stored, when I call *vec it then goes to that memory location on the heap. More on pointers in a later article.
The other method, example2(), just creates a new local vector and sets vec equal to it. You'll see why this is problematic later on. When the program is run in the order example1()$\to$ example2() everything will work fine. And here is the output:
The other method, example2(), just creates a new local vector and sets vec equal to it. You'll see why this is problematic later on. When the program is run in the order example1() -> example2() everything will work fine. And here is the output:
```
0

View File

@@ -2,7 +2,8 @@
{
title: "Writing better tests for Angular with Angular Testing Library",
description: "A simple explination of writing better tests for Angular applications and setting up Angular Testing Library",
published: "2020-05-09T04:45:30.247Z",
published: "2020-05-12T04:45:30.247Z",
edited: "2020-06-09T04:45:30.247Z",
authors: ["skatcat31"],
tags: ["testing", "unit tests", "angular"],
attached: [],
@@ -90,13 +91,12 @@ tsconfig.spec.json
}
```
The project also no longer needs the `test` key inside of `angular.json`, and thus it can be removed.
The project also no longer needs the `test` key inside of `angular.json` as it stands, and thus it's contents can be removed. Don't worry, we'll be making `ng test` work again later.
```json
angular.json
{
...,
"test": {...} <- delete
"test": {} <- delete contents, but leave the key
....
}
```
@@ -126,7 +126,7 @@ Now that the project has no Karma it can be setup with Jest
#### Install Jest
```bash
npm i -D @types/jest jest jest-preset-angular ts-jest
npm i -D @types/jest jest jest-preset-angular ts-jest @angular-builders/jest
```
This installs Jest, the types for Jest, a TypeScript pre-processor for Jest, and a preset that makes setting up Jest much easier.
@@ -192,7 +192,18 @@ package.json
}
```
Jest is now the test runner for the project. It can now be used to run the tests, but even better, it can be used in combination with Testing Library.
```json
angular.json
{
...,
"test": {
"builder": "@angular-builders/jest:run" <- new
}
....
}
```
Jest is now the test runner for the projectand it can be run with NPM, Yarn, or the Angular CLI. It can now be used in combination with Testing Library.
### Install Angular Testing Library