Проблема с & q заключается в том, что экземпляр структуры q находится в стеке выполнения во время работы метода. Даже если вы используете синтаксис new (), структура все еще находится в стеке. Таким образом, адрес всегда один и тот же (и станет недействительным, когда вы вернетесь из функции.) Если вы хотите получить указатель на структуру в куче (не кучу GC, а специальную область неуправляемой памяти), вы необходимо использовать AllocHGlobal для выделения памяти и затем привести IntPtr
к (poly*)
. Это неуправляемая память, поэтому вам также нужно помнить, чтобы освободить ее.
В общем, я думаю, что пытаться использовать C # таким способом - очень плохая идея, так как это сбивает с толку как программистов C #, так и C ++. Небезопасный синтаксис полезен в очень редких случаях, когда вам нужен быстрый доступ к основной памяти или для определенных сценариев взаимодействия. Использовать его для реализации структуры данных с помощью указателей в стиле C просто неправильно.
Вот конкретный пример, в случае, если вышесказанное неясно. Операция q = new poly();
просто заменяет содержимое q (локальной переменной в стеке) на недавно инициализированный poly (). Это больше похоже на очистку памяти, чем на выделение нового экземпляра. Это сбивает с толку, потому что в C ++ нет разницы между struct и class, когда дело доходит до выделения. New () в C ++ всегда размещается в куче. В C # место выделения обычно определяется типом , а не использованием, поэтому, когда вы вызываете new () для типа значения (struct), это сокращение для его инициализации, а не для выделения памяти для него. в кучу.
Вы задали вопрос о 'fixed', и есть очень хороший пример того, почему вы не должны использовать небезопасный C #, думая, что это в основном то же самое, что и C. В C # ссылки не такие же, как указатели. Одно из больших отличий заключается в том, что, поскольку ссылки на C # собираются мусором, GC может практически в любое время принять решение о перехвате выполнения вашей программы и заменить все ссылки, чтобы указать новых областей памяти . Если вы используете небезопасный код, который ссылается на указанную память через указатель, объект , на который ссылается указатель, может перемещаться без обновления указателя . Чтобы решить эту проблему, вы можете пометить конкретный экземпляр как «фиксированный», чтобы GC не мог его переместить. Компилятор C # пытается защитить вас от себя.