Снова скажу банальность, что эта тема является сверхважной, ибо по ссылкам и указателям (коробкам) происходит практически весь доступ к объектам в программировании, а еще доступ к переменным происходит по имени или операторами-методами, как при создании объектов с помощью операторов new, когда объект вызывается без коробок и без имени. Подробно о четырех способах доступа к объектам или переменным читайте статью на эту тему, которая скоро выйдет.
В языках C# и Java решили навести порядок с путаницей, которая происходит в языке C++ в случае использования ссылок и именных объектов. Путаница в том, что в языке С++ все объекты могут иметь коробки-ссылки, следовательно, когда вы записываете любой объект в С++ по имени или без имени, то эта запись может обозначать сам объект или ссылку на него, то есть получается в разных случаях запись объекта в С++ будет обозначать разные типы данных, в одном случае это будет коробка-ссылка, в другом сам объект. С указателями такой проблемы нет, так как они принимают адрес объекта в качестве своего значения в виде шестнадцатеричных целых чисел, а вот коробки-ссылки принимают адрес объекта в виде самой записи объекта, то есть ссылка равна тому объекту, на который она ссылается. Или коробка равна объекту, который виртуально лежит в данной коробке.
string ddd = new string (); // коробка от строки в C#
Например, в данной строке кода в C# создается коробка от строки с именем ddd у коробки, затем в эту коробку копируется адрес другой мгновенной коробки справа налево, то есть происходит шлюзовая операция копирования, когда мгновенная ссылка-коробка на постоянный созданный объект в памяти "куче" копируется в постоянную ссылку от строк ddd, то есть новый объект строки по умолчанию (пустая строка "") запихивается в коробку слева из мгновенной коробки справа, затем коробка справа (литерал ссылки) исчезает из памяти.
В реале компилятор не будет копировать мгновенную ссылку, как он не копирует константы, примитивные объекты, объекты с одной степенью свободы, компилятор просто в памяти сошлется на ту же строку и копирования в реале не будет, но копирование будет подразумевать программист в коде, но до этих "сложных" понятий мы пока не доросли, об этом позже.
string ddd = "vasja"; // объект строки в C++
В языке С++ та же по сути запись будет означать абсолютно другие вещи "под капотом" и это просто по причине того, что в С++ каждый объект может обладать ссылкой-коробкой, а может ею не обладать. Когда вы здесь записываете какой-то объект, то это может означать как коробку с ее значением в виде данного объекта, так и сам объект. В данном случае выше объект типа string (строка) слева с именем ddd копирует в себя значение литерала (мгновенного объекта) строки справа. В реале, как я написал выше, "под капотом" не происходит копирование литералов, а сразу создается объект уже в строку ddd.
string& ddd = "vasja"; // ссылка на объект в C++
А в таком варианте записи в С++ вы объявляете слева ссылку или коробку от строки с именем ddd у коробки, а справа вы закидываете литерал строки, который в данном контексте является мгновенной ссылкой подобно new String ( ) в языках C# и Java или мгновенной коробкой от мгновенной строки "vasja". Такая операция у вас в С++ может не пройти, так как мгновенный объект "vasja" исчезнет из памяти и на него нельзя ссылаться коробкой ddd, но операция копирования в С++ может быть переопределена "под капотом" для мгновенных объектов строк или мгновенных ссылок и тогда все пройдет гладко.
Смысл всего вышесказанного в том, что в С++ при записи объекта это может означать как коробку-ссылку, так и сам объект, а в Java и C# такое исключено в принципе по причине введения абсолютно безкоробочных объектов (структуры C# и "оберточные примитивные" типы Java) и объектов только со значениями коробок-ссылок (class в языках C# и Java), то есть в Java и C# у вас безкоробочные объекты никогда не могут иметь коробку-ссылку и записываться в виде значений ссылок, а коробочные объекты (классы) наоборот не могут записываться в виде объекта, они всегда являются ссылками слева и справа, на входе и выходе.
String www = new String ( ); // C# и Java
Слева здесь объявляется ссылка с именем www, справа здесь объявляется мгновенная ссылка (коробка) на новый постоянный объект типа (класса) строки, созданный оператором new в большой памяти "кучи", то есть всегда в Java и C# слева и справа в шлюзовых операциях ссылок будут ссылки, а в шлюзовых операциях объектов будут безкоробочные объекты.
Отсюда и возникает проблема "упаковок" и "распаковок" в Java и C# , которой нет в языке C++ , то есть когда вы в ссылку или класс в C# и Java запихиваете структуру или "оберточный" тип, то вы запихиваете в коробку безкоробочный объект, при этом происходит приведение типа, создается хреновая копия объекта из памяти "стека" и в большой памяти "кучи" создается аналогичный, но другого типа объект, а еще дополнительно происходит копирование коробок и возможно приведение коробок к меньшему размеру при расширяющем наследовании. При "распаковке" происходит наоборот просто хреновое "копирование" объекта из "кучи" в сверхбыструю память "стека", коробка от объекта здесь не требуется.
Вы должны усвоить главную мысль написания данной статьи, то есть безкоробочные объекты и объекты с коробками в Java и C# являются "кастрированными типами", то есть структуры и "оберточные примитивные" типы не могут иметь коробок-ссылок, и плюс к ним невозможно обратиться по ссылке, а только по именам объекта и можно еще по указателю в C#. Наоборот, классы или ссылки в C# и Java создают только коробочные объекты, то есть объект не может жить без хотя бы одной коробки, а в случае отсутствия даже одной ссылки на него объект уничтожается (не сразу) автоматическим "сборщиком мусора". К ссылочным объектам нельзя обращаться по имени объекта, а только по ссылкам.
При создании ссылочных объектов C# и Java оператором new создается мгновенная литеральная ссылка на постоянный объект, которая обычно сразу копируется в постоянную коробку при шлюзовой операции создания объектов классов. "Сборщик мусора" через какое-то время удаляет безымянные объекты, если у них нет ни одной коробки-ссылки!
Random sss = new Random (10);
При создании безкоробочных объектов Java и C# всегда доступ здесь только по имени, а при их создании доступ с помощью оператора new или литерала, при этом "под капотом" создается мгновенный безымянный объект и он копируется в объект с именем при шлюзовой операции. "Сборщик мусора" здесь не нужен, ибо доступ к объектам только по имени и мгновенными литералами!
int name1 = new int (6); // справа мгновенный литерал
int name2 = 78; // справа мгновенный явный литерал
Ну вот и пока сделаем перерыв, по этой тематике еще много для вас надеюсь сделать статей и мыслей, а в данной статье главной мыслью было для вас показать две разных сущности коробочных объектов и безкоробочных объектов в Java и C#, причем коробочные объекты могут жить какое-то время без коробки, пока их не удалит "сборщик мусора", и второй мыслью было для вас показать в С++ двойную природу любых объектов, которые могут быть как в коробке-ссылке, так и без коробки, что создает небольшую путаницу иногда при работе со ссылками в С++.