Cpp ссылка на указатель
Указатели поддерживают ряд операций: присваивание, получение адреса указателя, получение значения по указателю, некоторые арифметические операции и операции сравнения.
Присваивание адреса
Указателю можно присвоить адрес объекта того же типа, либо значение другого указателя. Для получения адреса объекта используется операция & :
int a ; int *pa ; // указатель pa хранит адрес переменной a
При этом указатель и переменная должны иметь один и тот же тип, в данном случае это тип int.
Разыменование указателя
Операция разыменования указателя представляет выражение в виде *имя_указателя . Эта операция позволяет получить объект по адресу, который хранится в указателе.
#include int main() < int a ; int *pa ; // хранит адрес переменной a std::cout #include int main() < int a ; int b ; int *pa ; // указатель на переменную a int *pb ; // указатель на переменную b std::cout pa: address=0x56347ffc5c value=10 pb: address=0x56347ffc58 value=2 pa: address=0x56347ffc58 value=2 b value=125
Нулевые указатели
Нулевой указатель (null pointer) - это указатель, который не указывает ни на какой объект. Если мы не хотим, чтобы указатель указывал на какой-то конкретный адрес, то можно присвоить ему условное нулевое значение. Для определения нулевого указателя можно инициализировать указатель нулем или константой nullptr :
Ссылки на указатели
Так как ссылка не является объектом, то нельзя определить указатель на ссылку, однако можно определить ссылку на указатель. Через подобную ссылку можно изменять значение, на которое указывает указатель или изменять адрес самого указателя:
#include int main() < int a ; int b ; int *p<>; // указатель int *&pRef
; // ссылка на указатель pRef = &a; // через ссылку указателю p присваивается адрес переменной a std::cout &:
int a ; int *pa ; std::cout >, >=, , ,==, !=. Операции сравнения применяются только к указателям одного типа. Для сравнения используются номера адресов:
#include int main() < int a ; int b ; int *pa ; int *pb ; if(pa > pb) std::cout
Консольный вывод в моем случае:
pa (0xa9da5ffdac) is greater than pb (0xa9da5ffda8)
Приведение типов
Иногда требуется присвоить указателю одного типа значение указателя другого типа. В этом случае следует выполнить операцию приведения типов с помощью операции (тип_указателя *) :
#include int main() < char c ; char *pc ; // указатель на символ int *pd <(int *)pc>; // указатель на int void *pv ; // указатель на void std::cout std::cout
Ссылки на указатели
Ссылки на указатели можно объявлять так же, как ссылки на объекты. Ссылка на указатель — это изменяемое значение, которое используется как обычный указатель.
Пример
В этом примере кода показана разница между использованием указателя на указатель и ссылки на указатель.
Функции Add1 и Add2 функционально эквивалентны, хотя они не называются по-разному. Разница заключается в том, что Add1 использует двойное косвенное обращение, но Add2 использует удобство ссылки на указатель.
// references_to_pointers.cpp // compile with: /EHsc #include #include // C++ Standard Library namespace using namespace std; enum < sizeOfBuffer = 132 >; // Define a binary tree structure. struct BTree < char *szText; BTree *Left; BTree *Right; >; // Define a pointer to the root of the tree. BTree *btRoot = 0; int Add1( BTree **Root, char *szToAdd ); int Add2( BTree*& Root, char *szToAdd ); void PrintTree( BTree* btRoot ); int main( int argc, char *argv[] ) < // Usage message if( argc < 2 ) < cerr char *szBuf = new char[sizeOfBuffer]; if (szBuf == NULL) < cerr // Read a text file from the standard input device and // build a binary tree. while( !cin.eof() ) < cin.get( szBuf, sizeOfBuffer, '\n' ); cin.get(); if ( strlen( szBuf ) ) < switch ( *argv[1] ) < // Method 1: Use double indirection. case '1': Add1( &btRoot, szBuf ); break; // Method 2: Use reference to a pointer. case '2': Add2( btRoot, szBuf ); break; default: cerr > > // Display the sorted list. PrintTree( btRoot ); > // PrintTree: Display the binary tree in order. void PrintTree( BTree* MybtRoot ) < // Traverse the left branch of the tree recursively. if ( MybtRoot->Left ) PrintTree( MybtRoot->Left ); // Print the current node. cout szText Right ) PrintTree( MybtRoot->Right ); > // Add1: Add a node to the binary tree. // Uses double indirection. int Add1( BTree **Root, char *szToAdd ) < if ( (*Root) == 0 ) < (*Root) = new BTree; (*Root)->Left = 0; (*Root)->Right = 0; (*Root)->szText = new char[strlen( szToAdd ) + 1]; strcpy_s((*Root)->szText, (strlen( szToAdd ) + 1), szToAdd ); return 1; > else < if ( strcmp( (*Root)->szText, szToAdd ) > 0 ) return Add1( &((*Root)->Left), szToAdd ); else return Add1( &((*Root)->Right), szToAdd ); > > // Add2: Add a node to the binary tree. // Uses reference to pointer int Add2( BTree*& Root, char *szToAdd ) < if ( Root == 0 ) < Root = new BTree; Root->Left = 0; Root->Right = 0; Root->szText = new char[strlen( szToAdd ) + 1]; strcpy_s( Root->szText, (strlen( szToAdd ) + 1), szToAdd ); return 1; > else < if ( strcmp( Root->szText, szToAdd ) > 0 ) return Add2( Root->Left, szToAdd ); else return Add2( Root->Right, szToAdd ); > >
Usage: references_to_pointers.exe [1 | 2] where: 1 uses double indirection 2 uses a reference to a pointer. Input is from stdin. Use ^Z to terminate input.
Ссылки на указатели
Ссылки на указатели можно объявлять так же, как ссылки на объекты. Ссылка на указатель — это изменяемое значение, которое используется как обычный указатель.
Пример
В этом примере кода показана разница между использованием указателя на указатель и ссылки на указатель.
Функции Add1 и Add2 функционально эквивалентны, хотя они не называются по-разному. Разница заключается в том, что Add1 использует двойное косвенное обращение, но Add2 использует удобство ссылки на указатель.
// references_to_pointers.cpp // compile with: /EHsc #include #include // C++ Standard Library namespace using namespace std; enum < sizeOfBuffer = 132 >; // Define a binary tree structure. struct BTree < char *szText; BTree *Left; BTree *Right; >; // Define a pointer to the root of the tree. BTree *btRoot = 0; int Add1( BTree **Root, char *szToAdd ); int Add2( BTree*& Root, char *szToAdd ); void PrintTree( BTree* btRoot ); int main( int argc, char *argv[] ) < // Usage message if( argc < 2 ) < cerr char *szBuf = new char[sizeOfBuffer]; if (szBuf == NULL) < cerr // Read a text file from the standard input device and // build a binary tree. while( !cin.eof() ) < cin.get( szBuf, sizeOfBuffer, '\n' ); cin.get(); if ( strlen( szBuf ) ) < switch ( *argv[1] ) < // Method 1: Use double indirection. case '1': Add1( &btRoot, szBuf ); break; // Method 2: Use reference to a pointer. case '2': Add2( btRoot, szBuf ); break; default: cerr > > // Display the sorted list. PrintTree( btRoot ); > // PrintTree: Display the binary tree in order. void PrintTree( BTree* MybtRoot ) < // Traverse the left branch of the tree recursively. if ( MybtRoot->Left ) PrintTree( MybtRoot->Left ); // Print the current node. cout szText Right ) PrintTree( MybtRoot->Right ); > // Add1: Add a node to the binary tree. // Uses double indirection. int Add1( BTree **Root, char *szToAdd ) < if ( (*Root) == 0 ) < (*Root) = new BTree; (*Root)->Left = 0; (*Root)->Right = 0; (*Root)->szText = new char[strlen( szToAdd ) + 1]; strcpy_s((*Root)->szText, (strlen( szToAdd ) + 1), szToAdd ); return 1; > else < if ( strcmp( (*Root)->szText, szToAdd ) > 0 ) return Add1( &((*Root)->Left), szToAdd ); else return Add1( &((*Root)->Right), szToAdd ); > > // Add2: Add a node to the binary tree. // Uses reference to pointer int Add2( BTree*& Root, char *szToAdd ) < if ( Root == 0 ) < Root = new BTree; Root->Left = 0; Root->Right = 0; Root->szText = new char[strlen( szToAdd ) + 1]; strcpy_s( Root->szText, (strlen( szToAdd ) + 1), szToAdd ); return 1; > else < if ( strcmp( Root->szText, szToAdd ) > 0 ) return Add2( Root->Left, szToAdd ); else return Add2( Root->Right, szToAdd ); > >
Usage: references_to_pointers.exe [1 | 2] where: 1 uses double indirection 2 uses a reference to a pointer. Input is from stdin. Use ^Z to terminate input.