2010-01-27 3 views
6

В C++ указатель - это указатель на адрес памяти, где хранится другая переменная, а в C# ссылка какая-то такая же. В чем разница между этими двумя?Разница между указателем в C++ и ссылочным типом в C#

+0

Просто прочитайте, что сказал лучший. ;-) http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx – Oliver

+0

Также см. Http://stackoverflow.com/questions/430112/what- is-the-difference-from-ac-sharp-reference-and-a-pointer – nawfal

ответ

8

В C# ссылочный тип будет автоматически собирать мусор, когда он больше не нужен.

0

Первое отличие состоит в том, что вы не можете использовать арифметику указателей на ссылки. В противном случае они почти одинаковы.

  • Обе точки/ссылка на фактический объект.
  • Оба могут быть NULL/нуль (т.е. не указывает на действительный объект)
  • Оба могут быть назначены новый объект

Другим отличием является то, что сборщик мусора заботится о выделенных ресурсов в C#. в C++, вы должны удалить их самостоятельно (или использовать смарт-указатель).

И, конечно же, вам не нужно вручную обращаться к ссылкам на C# для доступа к значению.

+0

oO Почему downvote? – Christian

+0

Недостаток не мой, но есть принципиальное отличие, которое вы игнорируете: .NET Runtime поддерживает как * абсолютный инвариант *, что никакая ссылка не может существовать в любой точке мира, о которой она не знает, вне одной особый случай: ссылки могут быть отмечены как «закрепленные», а внешние ссылки на закрепленные объекты могут существовать для отмеченных таким образом объектов, но наличие значительного количества закрепленных за один раз вредных воздействий на производительность GC. – supercat

0

C++ является указателем физического уровня, где хранится значение физического адреса. Ссылка C# скорее скрытый или непрозрачный указатель, где вы просто знаете, что это указывает на какой-то объект.

В C++ вы работаете с указателями либо на физическом уровне - операция с памятью, либо использовать его для доступа к объектам, на которые указывает.

// physical level operation 

// set pointer to specific address 
byte *pPointer = 0x00LB10; 
// increment pointer 
pPointer++; 

// OR 
// dereference operation for classes and structure 
pPointer->MyProperty 

В C# вы можете использовать ссылку (ссылку на объект типа) только для доступа к объектам.

MyReference.Property 
1

Так называемые ссылки в C# реализуются указателем на указатель на фактический объект. Они называются ручками, и хотя сам дескриптор остается фиксированным в течение всего жизненного цикла программы, внутренний указатель изменяется, когда объект перемещается в памяти сборщиком мусора во время фазы уплотнения памяти.

+0

В то время как различные реализации среды выполнения .NET и сборщика мусора были бы свободны в том, чтобы делать что-то по-другому, ссылки в общих реализациях .NET с сборщиком мусора в стоп-мире на самом деле являются прямыми указателями.Когда GC запускается, каждая ссылка на объект, который может перемещаться, будет посещаться и обновляться, чтобы отразить новое местоположение объекта. Скомпилированный код имеет специальные метаданные, связанные с ним, для каждой инструкции указывается, какие регистры содержат живые ссылки, а GC имеет возможность обновлять указатели, хранящиеся в этих регистрах. – supercat

1

Это разные звери. В C++ boost :: shared_ptr несколько похож на C# referenecs, но также является отличным зверем (из этих двух).

Ссылка указывает на объект, который будет утилизироваться сборщиком мусора. То же самое происходит в случае shared_ptr. Тем не менее, существует принципиальное различие между тем, как C# и boost :: shared_ptr работают с объектами дорожки (см. Ниже).

Указатели C++ могут указывать на что угодно, выделенные либо на стеке (в этом случае утилизация не требуется), статически на кучу, либо что-то выделенное вручную, по требованию, которое затем должно быть освобождено, и это полностью зависит от обязанность.

Различия между shared_ptr и C# ссылок:

shared_ptr представляет собой счетчик ссылок. Он подсчитывает, сколько клонов вашего указателя существует, и удаляет объект, если его нет. Это не дает решения против перекрестных ссылок (или круговых ссылок), когда A указывает на B, который указывает на A, но оба A и B больше не нужны.

C# сбор мусора занимается этим. C# не учитывает ссылки. Вместо этого он поддерживает список доступности - к чему можно получить доступ через все открытые указатели, которые у нас есть. То, что не может, расположено. Этот подход более безопасен, но имеет несколько недостатков с точки зрения предсказуемости производительности.

8

Для меня концепции такой же, или по крайней мере претендует на тот же самый, но фактическое использование дано, не.

Когда мы говорим о указателях или ссылках, мы говорим о концепции. Эта переменная «указывает на» или ее «ссылку» на что-то другое, что-то, что хранится где-то в другом месте.

Если я использую эту ссылку, например, путем обновления значения, я фактически обновляю ссылочный объект, объект, на который указывает переменная. Если у меня есть объект, ссылающийся на два разных места, я фактически обновляю одно и то же с обоих мест.

Таким образом, концепция может быть связана с вашим адресом в реальном мире, это просто способ ссылки на другую вещь, и эта ссылка может быть разделена, как и многие люди, имеющие мой адрес.

Разница больше в том, как она была использована и что было разрешено языком. Обратите внимание, что детали реализации ссылки или указателя не являются неявными в самой концепции. В C#, который по-прежнему остается верным.

Ссылка является ссылкой и тем, что так, это просто не имеет смысла суммировать две ссылки, или добавить ссылку на ссылку ... что бы это означало? Я не могу добавить два домашних адреса (например, Baker Street + Home Street) ...

В C++ деталь реализации ссылки на самом деле является ссылкой. Таким образом, указатель - это не просто указатель, его также (и используется как) адрес памяти. Таким образом, например, вы можете добавить указатели, потому что на самом деле имеет смысл добавить два адреса памяти для получения другого или добавить 4 в адрес памяти. Таким образом, в C++ указатель переставал быть концепцией, а стал именем, данным фактической детализации реализации.

Именно поэтому в C# указатели и ссылки - это разные вещи. Потому что семантически смысл очень похож, они хотели отличить от старой концепции C и C++, где указатель стал таким же, как адрес памяти.

Я рекомендую вам прочитать статью «References are not addresses» от Eric Lippert, где я считаю, что он отлично справляется с объяснением различий.

+2

Вы абсолютно не можете добавить два указателя в C++. – fredoverflow

Смежные вопросы