Добрый день!
Требуется создать связный список объектов структуры, в котором текущий элемент должен указывать на следующий, последний - на 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;
}
}
Ответ
Применительно к структуре, оператор 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;
}
}
Комментариев нет:
Отправить комментарий