Риск добавления к путанице, я хочу добавить некоторые входные данные, я уверен, что это в основном зависит от того, как компилятор реализует ссылки, но в случае gcc идея, что ссылка может указывать только на переменную в стеке на самом деле не правильно, возьмем это, например:
#include <iostream>
int main(int argc, char** argv) {
// Create a string on the heap
std::string *str_ptr = new std::string("THIS IS A STRING");
// Dereference the string on the heap, and assign it to the reference
std::string &str_ref = *str_ptr;
// Not even a compiler warning! At least with gcc
// Now lets try to print it's value!
std::cout << str_ref << std::endl;
// It works! Now lets print and compare actual memory addresses
std::cout << str_ptr << " : " << &str_ref << std::endl;
// Exactly the same, now remember to free the memory on the heap
delete str_ptr;
}
Что выводит это:
THIS IS A STRING
0xbb2070 : 0xbb2070
Если вы заметили, что даже адреса памяти точно совпадают, это означает, что ссылка успешно указывает на переменную в куче! Теперь, если вы действительно хотите стать причудливым, это также работает:
int main(int argc, char** argv) {
// In the actual new declaration let immediately de-reference and assign it to the reference
std::string &str_ref = *(new std::string("THIS IS A STRING"));
// Once again, it works! (at least in gcc)
std::cout << str_ref;
// Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
delete &str_ref;
/*And, it works, because we are taking the memory address that the reference is
storing, and deleting it, which is all a pointer is doing, just we have to specify
the address with '&' whereas a pointer does that implicitly, this is sort of like
calling delete &(*str_ptr); (which also compiles and runs fine).*/
}
Что выводит это:
THIS IS A STRING
Поэтому ссылка - это указатель под капотом, они оба просто хранят адрес памяти, где адрес, на который указывает адрес, не имеет значения, как вы думаете, что произойдет, если я вызову std :: cout << str_ref; ПОСЛЕ вызова delete & str_ref? Ну, очевидно, что он хорошо компилируется, но вызывает ошибку сегментации во время выполнения, потому что он больше не указывает на допустимую переменную, у нас, по сути, есть поврежденная ссылка, которая все еще существует (пока она не выпадает из области видимости), но бесполезна. </p>
Другими словами, ссылка - это не что иное, как указатель, у которого абстрагирована механика указателя, что делает его более безопасным и простым в использовании (без случайной математики указателя, без смешения '.' И '->' и т. Д.) при условии, что вы не пробуете чепуху, как мои примеры выше;)
Теперь независимо от того, как компилятор обрабатывает ссылки , он будет всегда иметь какой-то указатель под капотом, потому что ссылка должна ссылаться на конкретный переменная с определенным адресом памяти, чтобы он работал как положено, обойти это невозможно (отсюда и термин «ссылка»).
Единственное основное правило, которое важно помнить со ссылками, это то, что они должны быть определены во время объявления (за исключением ссылки в заголовке, в этом случае она должна быть определена в конструкторе, после того как объект содержится в, это слишком поздно, чтобы определить это).
Помните, мои примеры выше - это просто примеры, демонстрирующие, что такое ссылка, вы никогда не захотите использовать ссылку таким образом! Для правильного использования справочника здесь уже есть множество ответов, которые бьют по голове