diff options
add sem1
2 files changed, 75 insertions, 1 deletions
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | Seminar01/README.md | 73 |
@@ -1 +1,2 @@ -# Код от семинарита по СДП - Компютърни науки
\ No newline at end of file +# Код от семинариe по СДП - Компютърни науки +* Тема 1: Технически преговор - указатели и памет. Дефиниция на структура от данни. Сложност.
\ No newline at end of file diff --git a/Seminar01/README.md b/Seminar01/README.md new file mode 100644 index 0000000..ae6869a --- /dev/null +++ b/Seminar01/README.md @@ -0,0 +1,73 @@ +# Указатели и памет. + +## Указатели и референции. Работа с памет. +Указателите, които вече добре познаваме, са променливи, които съхраняват адреса на обект в паметта. Указателите най - често са използвани за: +* Да заделяме динамично памет в heap-а +* Итерираме елементите на масив или друга структура от данни +* Подаваме функции като аргументи на други функции +и много други. + +Указателите са удобен и изключително гъвкав инструмент, с който често ще ни се налага да работим. +Нека разгледаме следния сценарии. +```c++ +int main() { + int a = 10; + int b = 12; + int* ptr = &a; +} +``` +Искаме да напишем функция, която приема указател и променлива и кара указателя да сочи към тази променлива. Дали следния код ще свърши работа: +```c++ +#include<iostream> + +void redirect(int* ptr, int dest) { + ptr = &dest; +} + +int main() { + int a = 10; + int b = 12; + int* ptr = &a; + + redirect(ptr, b); + std::cout << *ptr; // *ptr връща стойността записана в този адрес +} +``` +Очевидно това не сработи, но защо? Във функцията *redirect* на *ptr* се прави **копие**. После това копие започва да сочи към *dest*, но на нас това не ни помага! Ние искаме да пренасочим **самия указател а не неговото копие**. Тук на помощ идват референциите (или псевдонимите)! Ако пренапишем функцията по следния начин + +```c++ +void redirect(int*& ptr, int dest) { + ptr = &dest; +} +``` +то вече функцията върши желаната задача. Когато приемаме обект по референция **копие не се прави**. Това важи за всички типове - включително и за указателите. +Можем да правим указатели към всякакви типове включително и към указатели. Типът **int**** не е нищо повече от указател към указател. + +Тогава не можем ли просто да вземем указател към указателя и да го променим по този начин? +```c++ +#include<iostream> + +void redirect(int** ptr, int dest) { + *ptr = &dest; +} + +int main() { + int a = 10; + int b = 12; + int* ptr = &a; + + redirect(&ptr, b); // &ptr връща адреса на указателя, точно това което е int**, адрес на указател. + std::cout << *ptr; +} +``` + +Този код също върши работа. Тогава каква е разликата между указател и референция? +Разликата е, че указателите са по - гъвкави. Не можем да пренасочим референция. Също така не можем да имаме референция която не сочи към обект. При указателите имаме специален тип наречен nullptr, който сочи към "нищото". Често референцията е представяна като указател, който не може да се пренасочва, вика *** вместо теб и винаги сочи към обект. + +## const и указателите +За *const* важи следното правило - *const* винаги модифицира това което е в негово ляво, освен когато няма нищо отляво, тогава модифицира това което е отдясно. + +* const int* -> Указател, който сочи към константен *int*. Можем да пренасочваме, но не можем да променяме стойността. +* int const* -> Абсолютно същото. +* int * const -> Константен указател, не можем да го пренасочваме. +* const int* const -> Константен указател към константен *int*. Нито можем да пренасочваме нито да променяме стойността.
\ No newline at end of file |
