You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
are used to store the address of the varibale/object in memory. So having the pointer or reference, you could do the same operations as that of object being pointed to.
855
-
```c++
856
-
int a = 3;
857
-
int b = 5;
852
+
Those familiar with C will be very intimately acquainted with pointers. C++ adds the concept of references, which is a powerful way to have *some* of the features of
853
+
pointers while avoiding some of the pitfalls. Later versions of C++ also add [smart pointers](https://docs.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp?view=vs-2019),
854
+
which allow for better memory management and scoping via `std::unique_ptr`, `std::shared_ptr`, and `std::weak_ptr`, as compared to traditional raw pointers.
858
855
859
-
int* aptr = &a; // & operator gets the address of variable a
860
-
int* bptr = &b; // int * is a type of pointer to int
856
+
Raw pointers in C++ behave exactly the same way as they do in C: a pointer variable stores the address of whatever it is pointing to. You can think of pointers as
857
+
essentially storing a link to another piece of data. You can access the data that the pointer points to with the `->` operator, or dereference it with the `*` operator.
858
+
859
+
References are more akin to an alias. References cannot be `NULL` or `nullptr`, and references cannot be reassigned to reference something else after they have been created.
860
+
Additionally, references do not take up extra memory; they share the same address as whatever they reference to. References cannot have multiple levels of indirection (pointers can),
861
+
and there is no reference arithmetic like there is for pointers. You can access the underlying data of a reference directly by using the reference itself: that is, if it's a reference
862
+
to an integer it can be used as an integer. If it's a reference to a class you can access the class members directly with the `.` operator.
863
+
864
+
Although pointers are incredibly powerful, references are generally much safer, especially when passing objects to methods using pass-by-reference. It is very common in
865
+
C++ code to pass an object as a `const` reference (if the data should be unmutable within the method) or a non-const reference rather than a raw pointer as is required in C.
866
+
867
+
More on [references vs pointers here](https://stackoverflow.com/a/57492).
868
+
869
+
In the following code, assume a 32-bit system, in which case the size of a pointer variable is 4 bytes (32 bits), and that the stack grows towards higher memory addresses.
861
870
862
-
int c = *aptr + *bptr; // * opeartor used to get the value of the object that
863
-
// is being pointed to
864
-
int d = a + b; // c and d are equal at the end of the day
865
-
```
866
-
Think of pointer as the abstraction that knows where to find an object, but don't own it.
867
-
The references are about the same, but they use more convenient syntax, but some [limitations](https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in) apply. The main difference is that refernce can't be reassigned and must be assigned at initialization:
868
871
```c++
869
-
int a = 3;
870
-
int b = 5;
872
+
// Pointers
873
+
int a = 10; // Ends up at memory address '0x2A000084', for example
874
+
int b = 20; // Ends up at memory address '0x2A000088'
871
875
872
-
int& aref = a; //& means reference type
873
-
int& bref = b;
876
+
int * ptr = nullptr; //ptr is a separate variable whose type is 'pointer to int' and whose value has been initialized to '0x00000000'
877
+
printf("ptr = %p\n"); // Prints: 0x0
874
878
875
-
int c = aref + bref; // simple addition syntax
879
+
ptr = &a; // The value of ptr is now the address of the variable 'a'
880
+
std::cout << p << std::endl; // Prints: 0x2a000084
881
+
std::cout << *p << std::endl; // Prints: 10
876
882
877
-
int d = a + b; // c and d are equal at the end of the day
883
+
ptr = &b; // The value of ptr is now the address of the variable 'b'
884
+
std::cout << p << std::endl; // Prints: 0x2a000088
885
+
std::cout << *p << std::endl; // Prints: 20
878
886
```
879
-
Also pointers are used in arrays like that:
887
+
880
888
```c++
881
-
#include<iostream>
889
+
// References
890
+
int a = 10; // Ends up at memory address '0x2A000084', for example
891
+
int b = 20; // Ends up at memory address '0x2A000088'
ptr = arr; // reassignment of pointer, can't be preformed with reference
894
-
for(int i = 0; i < size; i++) std::cout << *(ptr++) << ' '; // 9 5 8 2
895
-
std::cout << '\n'
896
-
```
897
-
This loops are equivalent, moreover first-second are implemented in the same way. First loop is just convenience syntax for second. Notice, that pointers can be incremented. Also there are a special pointer, called `nullptr`.
898
-
```c++
899
-
double* ptr = nullptr; // means it points to nowhere
902
+
ref_a = b; // SETS THE VALUE OF 'a' TO THE VALUE OF 'b'!
900
903
901
-
double a = *ptr; // this is a huge error, DON'T DO THIS
904
+
std::cout << ref_a << std::endl; // Prints: 20
905
+
std::cout << a << std::endl; // ALSO PRINTS: 20 !
906
+
907
+
int & ref_c; // ERROR! References must be initialized at their declaration
`what` is a standard name for a function that tells what's happened in the exception class.
1028
974
### 2.8 Lambdas
1029
-
Very common pattern is to write such a code:
1030
-
```c++
1031
-
structAddTo3 {
1032
-
int operator()(int addto) const { return 3 + addto; }
1033
-
};
1034
-
1035
-
int add_to_3(int addto) { return 3 + addto; }
1036
-
// basically the same, but it is not enough in some cases
1037
-
1038
-
// usage
1039
-
int main()
1040
-
{
1041
-
(AddTo3 {})(5); // 8
1042
-
add_to_3(5); // 8
1043
-
}
1044
-
```
1045
-
It is so common, that language designers decided to add it to the standard and call it `lambda function`:
1046
-
```c++
1047
-
int main()
1048
-
{
1049
-
auto add_to_3 { // much, much simpler, just declare variable add_to_3
1050
-
[] (int addto) { return 3 + addto; }
1051
-
};
1052
-
1053
-
add_to_3(5);
1054
-
}
1055
-
```
1056
-
Now, what this syntax means:
1057
-
```c++
1058
-
intmain()
1059
-
{
1060
-
auto add_to_3 {
1061
-
[] // 1
1062
-
/**
1063
-
* Capture variables, from outer scope, by reference(&),
1064
-
* or by value(=).
1065
-
* [&] - captures all variables by reference(uses them inside lambda)
1066
-
* [=] - captures all variables by value(copies them inside lambda)
1067
-
* [&var] - capture only var by reference
1068
-
* [=var] - capture only var by value
1069
-
* [=, &var] capture var by ref, and others by value
1070
-
*/
1071
-
(int addto) // 2
1072
-
/**
1073
-
* Argument list, just like in ordinary functions
1074
-
*/
1075
-
{ return 3 + addto; } // 3
1076
-
/**
1077
-
* Lambda body, just like in ordinary functions
1078
-
*/
1079
-
};
1080
-
1081
-
add_to_3(5); // 8
1082
-
}
1083
-
```
1084
-
So you could use it in advanced scenarios. Read more, like [this](https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11), and [that](https://en.cppreference.com/w/cpp/language/lambda).
0 commit comments