Ссылки на C ++ принципиально отличаются от ссылок на языках Java или .NET; Языки .NET имеют специальные типы, называемые «byrefs», которые во многом похожи на «ссылки» C ++.
Ссылка C ++ или .NET byref (я буду использовать последний термин, чтобы отличать ссылки .NET) - это специальный тип, который не содержит переменную, а скорее содержит информацию, достаточную для идентификации переменной (или чего-то еще). который может вести себя как единое целое (например, слот массива), хранящийся в другом месте. Byrefs обычно используются только в качестве параметров / аргументов функции и предназначены для эфемерности. Код, который передает byref функции, гарантирует, что идентифицируемая переменная будет существовать, по крайней мере, до тех пор, пока эта функция не будет возвращена, а функции обычно гарантируют, что не сохранят ни одной копии byref после своего возврата (обратите внимание, что в C ++ последнее ограничение не исполнение). Таким образом, byrefs не может пережить идентифицированные им переменные.
В языках Java и .NET ссылка - это тип, который идентифицирует объект кучи; Каждый объект кучи имеет связанный класс, и код в классе объекта кучи может получить доступ к данным, хранящимся в объекте. Объекты кучи могут предоставлять внешнему коду ограниченный или полный доступ к хранящимся в нем данным и / или разрешать внешнему коду вызывать определенные методы в своем классе. Использование ссылки на вызов метода своего класса приведет к тому, что эта ссылка станет доступной для этого метода, который затем может использовать ее для доступа к данным (даже частным данным) в объекте кучи.
Что делает ссылки особенными в языках Java и .NET, так это то, что они поддерживают в качестве абсолютного инварианта, что каждая ненулевая ссылка будет продолжать идентифицировать один и тот же объект кучи, пока эта ссылка существует. Как только нигде во вселенной не существует ссылки на объект кучи, объект кучи просто перестанет существовать, но нет никакого способа, которым объект кучи может прекратить существовать, пока существует какая-либо ссылка на него, и нет никакого способа для «нормального» msgstr "ссылка на объект кучи, чтобы самопроизвольно стать чем-либо, кроме ссылки на этот объект. И Java, и .NET имеют специальные типы «слабых ссылок», но даже они поддерживают инвариант. Если в юниверсе не существует неслабых ссылок на объект, то любые существующие слабые ссылки будут признаны недействительными; как только это произойдет, не будет никаких ссылок на объект, и поэтому он может быть признан недействительным.
Указатели, такие как ссылки C ++ и ссылки Java / .NET, идентифицируют объекты, но в отличие от вышеупомянутых типов ссылок они могут переживать идентифицируемые ими объекты. Если объект, идентифицированный указателем, перестает существовать, но сам указатель не существует, любая попытка использовать указатель приведет к неопределенному поведению. Если указатель не известен как null
или для идентификации объекта, который существует в настоящее время, не существует стандартного способа сделать что-либо с этим указателем, кроме как перезаписать его чем-то другим. Вполне допустимо, чтобы указатель продолжал существовать после того, как идентифицированный таким образом объект перестал это делать, при условии, что ничто никогда не использует указатель, но необходимо, чтобы что-то вне указателя указывало, безопасно ли его использовать, потому что нет способа спроси сам указатель.
Ключевое различие между указателями и ссылками (любого типа) заключается в том, что ссылки всегда можно спросить, являются ли они действительными (они будут либо действительными, либо идентифицируемыми как нулевые), и если они будут считаться действительными, они останутся таковыми Пока они существуют. Указатели нельзя спрашивать, действительны ли они, и система не будет делать ничего, чтобы гарантировать, что указатели не станут недействительными, и не позволит указателям, которые стали недействительными, быть признанными как таковые.