#c_sharp #указатели
Добрый день!
Требуется создать связный список объектов структуры, в котором текущий элемент должен
указывать на следующий, последний - на null. На C++ когда делал подобное - проблем
не возникло. На C# первый элемент создается без проблем. Но второй создается с тем-же
адресом! Как это исправить?
// Структура объектов очереди
struct QueueItem
{
public int Value;
public unsafe QueueItem* Next;
public unsafe QueueItem(int value) : this()
{
Value = value;
Next = null;
}
}
class QueueWithMinStats
{
private unsafe QueueItem* _first;
private unsafe QueueItem* _last;
public unsafe QueueWithMinStats()
{
_first = null;
_last = null;
}
// Добавить в очередь значение
public unsafe void Enqueue(int value)
{
// Проблема тут!!!
var newItem = new QueueItem(value);
var newItemLink = &newItem;
if (_first == null) // Если вводимый элемент - первый
_first = newItemLink;
else
_last->Next = newItemLink;
_last = newItemLink;
}
}
Ответы
Ответ 1
Применительно к структуре, оператор new не выделяет память, а лишь вызывает конструктор. Сама структура каждый раз создается на стеке в одном и том же месте - неудивительно что указатели одинаковы. Для того, чтобы структура "перенеслась" в кучу - надо кастануть ее к типу object (эта операция называется упаковкой). Но у упакованной структуры получить адрес средствами языка - не так-то и просто... Поэтому предлагаю вам сделать все по-другому. Во-первых, замените структуру на класс (значимый тип на ссылочный). Во-вторых, уберите указатели: для ссылочных типов они не нужны. Вместе с другими, не столь критичными, исправлениями, получится как-то так: class QueueWithMinStats { class QueueItem // я перенес этот класс внутрь, потому что за пределами реализации очереди он никому не должен быть интересен { public int Value; public QueueItem Next; public QueueItem(int value) { Value = value; // Next инициализаровать не надо - поля классов инициализируются значениями по умолчанию автоматически } } private QueueItem _first; private QueueItem _last; // Конструктор пока не нужен public void Enqueue(int value) { // Проблемы больше нет!!! var newItem = new QueueItem(value); // Переменная newItemLink больше не нужна - потому что QueueItem - это ссылочный тип if (_first == null) // Если вводимый элемент - первый _first = newItem; else _last.Next = newItem; _last = newItem; } }
Комментариев нет:
Отправить комментарий