Иногда нужно быстро вспомнить как работать с указателями и ссылками в C++. Написал для себя пример кода-шпаргалку. Компилировал в MS Visual Studio 2017.
#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
void sum(int a, int b)
{
b = a + b;
printf("Результат внутри функции sum(100, var), var = %i\r\n", b);
}
void sumptr(int a, int* b)
{
*b = a + *b;
printf("Результат внутри функции sumptr(100, &var), var = %i\r\n", *b);
}
float sum(float x, float y)
{
return x + y;
}
float sub(float x, float y)
{
return x - y;
}
class One
{
public:
std::string Tag;
One() {}
};
class Two
{
public:
One* one;
std::string Tag;
int id;
void Check(int id, One* one)
{
this->id = id;
std::cout << "Id: " + std::to_string(this->id) + " " + one->Tag + "\r\n";
};
Two() {}
};
typedef std::vector<Two*> Twos;
class Three
{
public:
void* one; //One
std::string Tag;
Twos twos;
Three() {}
};
typedef std::vector<Three*> Threes;
int main()
{
setlocale(LC_ALL, "Rus");
Указатели в C++
int var; //Переменная типа int
int* ptrvar;
ptrvar = NULL; // Указатель на переменную типа int. Лучше инициализировать NULL, поскольку изначально указатель указывает на случайную область памяти.
printf("Адрес переменной ptrvar = %p (указатель инициализирован NULL)\r\n", ptrvar);
var = 100;
ptrvar = &var; //Сохраняем значение адреса переменной в указателе
printf("Значение переменной var = %i\r\n", var);
printf("Значение по указателю *ptrvar = %i\r\n\r\n", *ptrvar);
printf("Адрес переменной &var = %p\r\n", &var);
printf("Адрес переменной &var = %X\r\n", &var);
if (ptrvar)
{
printf("Адрес переменной ptrvar = %p\r\n", ptrvar);
}
else
{
printf("Указатель не определен\r\n");
}
float value = 100.65;
//int *ptrvar = &value; //Если раскомментировать, то будет ошибка, поскольку float не может быть размещен в указателе ссылающемся на переменную типа intАдрес переменной ptrvar = 00000000 (указатель инициализирован NULL)
Значение переменной var = 100
Значение по указателю *ptrvar = 100
Адрес переменной &var = 00F5FAF4
Адрес переменной &var = F5FAF4
Адрес переменной ptrvar = 00F5FAF4
Указатель на любой тип данных void* в C++
printf("\r\n--------------Указатель на любой тип данных void*---------------------\r\n");
void *ptrvoid; //Указатель на любой тип данных
ptrvoid = &var;
int* ptrvar1 = static_cast<int*>(ptrvoid); //Можно привести к нужному типу так
printf("Адрес переменной var = %p, значение переменной var = %i\r\n", ptrvar1, *ptrvar1);
ptrvoid = &value;
float* ptrvar2 = (float*)ptrvoid; //Можно привести к нужному типу и так
printf("Адрес переменной var = %p, значение переменной var = %f\r\n", ptrvar1, *ptrvar2);—————Указатель на любой тип данных void*———————
Адрес переменной var = 00F5FAF4, значение переменной var = 100
Адрес переменной var = 00F5FAF4, значение переменной var = 100,650002
Указатель в аргументах функции
в C++
printf("\r\n--------------Указатель в аргументах функции--------------------------\r\n");
sum(100, var);
printf("Результат sum(100, var) вне функции, var = %i\r\n\r\n", var);
sumptr(100, &var);
printf("Результат sumptr(100, &var) вне функции, var = %i\r\n", var);—————Указатель в аргументах функции—————————
Результат внутри функции sum(100, var), var = 200
Результат sum(100, var) вне функции, var = 100
Результат внутри функции sumptr(100, &var), var = 200
Результат sumptr(100, &var) вне функции, var = 200
Указатель на функцию
в C++
printf("\r\n--------------Указатель на функцию--------------------------\r\n");
void(*ptrsum)(int, int*) = sumptr; //Указатель обязательно должен быть в скобках. Если void *message (void); - будет прототип функции message, возвращающей тип void.
ptrsum(100, &var); //Используем ссылку на функцию
printf("Результат ptrrf(100, &var) вне функции, var = %i\r\n", var);—————Указатель на функцию—————————
Результат внутри функции sumptr(100, &var), var = 300
Результат ptrrf(100, &var) вне функции, var = 300
Массив указателей на функции
в C++
printf("\r\n--------------Массив указателей на функции--------------------------\r\n");
float(*ops[2])(float, float) = { sum, sub };
float a = sizeof(ops);
float b = sizeof(float);
float c = sizeof(ops[0]);
int len = a / b;
printf("Sizeof(ops) = %i, sizeof(float) = %i, sizeof(ops[0]) = %i, len = %i\r\n", (int)a, (int)b, (int)c, len);
for (int i = 0; i < len; i++)
{
printf("Результат ops[%i](a, b) = %f\r\n", i, ops[i](a, b));
}—————Массив указателей на функции—————————
Sizeof(ops) = 8, sizeof(float) = 4, sizeof(ops[0]) = 4, len = 2
Результат ops[0](a, b) = 12,000000
Результат ops[1](a, b) = 4,000000
Ссылка на переменную
в C++
printf("\r\n--------------Ссылки---------------------------------------------------\r\n");
int &pvar = var; // Объявляем ссылку на переменную var. Теперь p это псевдоним pvar
printf("Адрес переменной var = %p, значение var = %i\r\n", &var, var);
printf("Адрес ссылки var = %p, значение pvar = %i\r\n", &pvar, pvar);—————Ссылки—————————————————
Адрес переменной var = 00F5FAF4, значение var = 300
Адрес ссылки var = 00F5FAF4, значение pvar = 300
Ссылка на функцию
в C++
printf("\r\n--------------Ссылка на функцию---------------------------------------\r\n");
void(&rf)(int, int*) = sumptr;
rf(100, &var); //Используем ссылку на функцию
printf("Результат rf(100, &var) вне функции, var = %i\r\n", var);—————Ссылка на функцию—————————————
Результат внутри функции sumptr(100, &var), var = 400
Результат rf(100, &var) вне функции, var = 400
Резервирование памяти под переменную вручную
в C++
printf("\r\n--------------Резервирование памяти под переменную вручную------------\r\n");
int *ptrint = new int; //Вручную зарезервировали область памяти под переменную типа int
printf("Адрес переменной ptr = %p\r\n", ptrint);
*ptrint = 100.65; //Помещаем значение не соответствующее типу int
printf("Значение переменной ptrint = %i\r\n", *ptrint);
printf("Значение переменной ptrint = %f\r\n", *ptrint); //Из-за несоответствия выведет неверную информацию
*ptrint = 100;
(*ptrint)++; //Инкремент переменной
printf("Значение inc переменной ptrint = %i\r\n", *ptrint);
delete ptrint; //Удаление вручную зарезервированной области памяти.
float *ptrfloat = new float; //Вручную зарезервировали область памяти под переменную типа float
*ptrfloat = 100.65;
printf("Значение переменной ptr = %f\r\n", *ptrfloat);
delete ptrfloat;—————Резервирование памяти под переменную вручную————
Адрес переменной ptr = 010EE888
Значение переменной ptrint = 100
Значение переменной ptrint = 0,000000
Значение inc переменной ptrint = 101
Значение переменной ptr = 100,650002
Динамическое создание одномерного массива
в C++
printf("\r\n--------------Динамическое создание одномерного массива----------------\r\n");
int size = 3;
int *ptrarr = new int[size]; //Динамически задаем размер массива
for (int i = 0; i < 3; i++)
{
*(ptrarr + i) = 9 - i; //Помещаем элемент в массив через указатель
printf("Array address (ptrarr + %i) = %p, *(ptrarr + %i) = %i, ptrarr[%i] = %i\r\n", i, (ptrarr + i), i, *(ptrarr + i), i, ptrarr[i]);
ptrarr[i] = i; //Помещаем элемент в массив обычным способом
printf("Array address &ptrarr[%i] = %p, ptrarr[%i] = %i\r\n\r\n", i, &ptrarr[i], i, ptrarr[i]);
}
delete[]ptrarr;—————Динамическое создание одномерного массива—————-
Array address (ptrarr + 0) = 010EF6E0, *(ptrarr + 0) = 9, ptrarr[0] = 9
Array address &ptrarr[0] = 010EF6E0, ptrarr[0] = 0
Array address (ptrarr + 1) = 010EF6E4, *(ptrarr + 1) = 8, ptrarr[1] = 8
Array address &ptrarr[1] = 010EF6E4, ptrarr[1] = 1
Array address (ptrarr + 2) = 010EF6E8, *(ptrarr + 2) = 7, ptrarr[2] = 7
Array address &ptrarr[2] = 010EF6E8, ptrarr[2] = 2
Динамическое создание двумерного массива
в C++
printf("\r\n--------------Динамическое создание двумерного массива-----------------\r\n");
const int size1 = 2;
const int size2 = 3;
// двумерный массив размером 2x3
int** i_arr = new int*[size1];
for (int i = 0; i < size1; i++) {
int *ptrint = new int[size2]; //Создаем указатель на двумерный массив
i_arr[i] = ptrint; // new int[size2]; //Заполняем каждую строку одномерного массива указателей размером size1 указателями на одномерный массив указателей размером size2
printf("В i_arr[%i] = %X, ptrint = %p\r\n", i, i_arr[i], ptrint);
for (int j = 0; j < size2; j++)
{
i_arr[i][j] = i + 10 * j;
}
printf("i_arr[%i][0] = %i, i_arr[%i][1] = %i, i_arr[%i][2] = %i\r\n", i, i_arr[i][0], i, i_arr[i][1], i, i_arr[i][2]);
for (int j = 0; j < size2; j++)
{
*(ptrint + j) = i + 10 * j;
}
*(i_arr + i) = ptrint;
printf("i_arr[%i][0] = %i, i_arr[%i][1] = %i, i_arr[%i][2] = %i\r\n", i, i_arr[i][0], i, i_arr[i][1], i, i_arr[i][2]);
}
delete(i_arr);—————Динамическое создание двумерного массива——————
В i_arr[0] = 10EF558, ptrint = 010EF558
i_arr[0][0] = 0, i_arr[0][1] = 10, i_arr[0][2] = 20
i_arr[0][0] = 0, i_arr[0][1] = 10, i_arr[0][2] = 20
В i_arr[1] = 10EF130, ptrint = 010EF130
i_arr[1][0] = 1, i_arr[1][1] = 11, i_arr[1][2] = 21
i_arr[1][0] = 1, i_arr[1][1] = 11, i_arr[1][2] = 21
Шаблон vector
в C++
printf("\r\n--------------Шаблон vector-----------------\r\n");
Threes threes;
for (int i = 0; i < 3; i++)
{
Three* three = new Three();
three->Tag = "Three tag " + std::to_string(i);
One* one = new One();
one->Tag = "One tag " + std::to_string(i);
three->one = one;
Twos twos;
for (int i = 0; i < 2; i++)
{
Two* two = new Two();
two->Tag = "Two tag " + std::to_string(i);
two->Check(i, one);
twos.push_back(two);
}
three->twos = twos;
threes.push_back(three);
}
for (Three* three : threes)
{
std::cout << three->Tag + "\r\n";
std::cout << ((One*)three->one)->Tag + "\r\n";
for (Two* two : three->twos)
{
std::cout << "\t" + two->Tag + "\r\n";
}
}
}—————Шаблон vector——————
Id: 0 One tag 0
Id: 1 One tag 0
Id: 0 One tag 1
Id: 1 One tag 1
Id: 0 One tag 2
Id: 1 One tag 2
Three tag 0
One tag 0
Two tag 0
Two tag 1
Three tag 1
One tag 1
Two tag 0
Two tag 1
Three tag 2
One tag 2
Two tag 0
Two tag 1