C # еквівалент вектора C ++, з суміжною пам’яттю?


85

Що таке еквівалент C # вектору C ++?

Я шукаю цю функцію:

Мати динамічний масив сусідньо збереженої пам'яті, який не вимагає показників продуктивності за доступ до стандартних масивів.

Я шукав, і вони кажуть .NET equivalent to the vector in C++ is the ArrayList, так:

Чи має ArrayList таку суміжну функцію пам'яті?


4
Хіба CLR недостатньо близький до металу, щоб ви могли вказати (або навіть послідовно очікувати), як структура розподіляється в пам'яті?
Aphex

Відповіді:


101

Ви можете використовувати тип значення List<T>and, коли Tце значення, воно буде виділено у суміжну пам'ять, чого не буде, якщо Tце посилальний тип.

Приклад:

List<int> integers = new List<int>();
integers.Add(1);
integers.Add(4);
integers.Add(7);

int someElement = integers[1];

2
@cMinor, документація List<T>класу містить багато прикладів, але я оновив свою відповідь, включивши таку.
Дарін Димитров

5
Я не на 100% знайомий з CLR, але має сенс, що навіть якщо Tце посилальний тип, ви все одно матимете суміжну пам'ять. В основному це масив покажчиків ...
josaphatv

"що не було б, якщо T є еталонним типом" - це так само, як і для T[]... ОП просив "не вимагати показників за доступність порівняно зі стандартними масивами" і List<T>передбачає це. І якщо Tце посилальний тип, це аналогічно T*C ++, тож ви отримуєте стільки ж суміжності, як і в C ++. Якщо хтось хоче, щоб самі об’єкти були суміжними, тоді, звичайно, потрібні типи значень ... в обох мовах. Звичайно, різниця полягає в тому, що в C ++ будь-який тип можна використовувати як значення, так і як ref, тоді як у C # це властивість типу за допомогою відмінності класу / структури.
Jim Balter

Сьогодні чогось навчився. Я думав, що List<T>це завжди реалізується як зв’язаний список внутрішньо. То як він динамічно розширюється тоді, коли ми телефонуємо Add()? Щось на зразок VB6, Redim Preserveякий раніше копіював весь масив у нове місце?
dotNET

@dotNet, внутрішньо List<T>створює невеликий масив T[]. Елементи внутрішньо додаються до масиву. Після того, як розмір масиву завершено, новий масив створюється подвійним розміром попереднього. Дані копіюються в новий більший масив, менший знищується тощо. Розробник може дати натяк на .NET , щоб створити досить великий внутрішній масив перед заповненням з List допомогою конструктора: new List<T>(expected_array_size).
Артру

16

використання List<T>. Внутрішньо він використовує масиви, а масиви використовують суміжну пам'ять.


2
Не зовсім правда. Якщо T є еталонним типом, суміжної пам'яті не буде.
Маттео Моска,

2
@Matteo, якщо ви подивитесь на джерело, там private T[] _items;використовується для внутрішнього зберігання, тип посилання чи ні.
Bala R

13
Ну, я це знаю. Але скажи мені. У вас є List <SomeClass>. Посилання на екземпляри SomeClass зберігатимуться у суміжній пам'яті, але не самі екземпляри. Як еталонні типи, вони будуть у купі, і ви напевно знаєте, як ця купа працює.
Маттео Моска,

@MatteoMosca, зберігаючи посилання безперервно, принаймні видаляє один рівень опосередкованості. Краще, ніж нічого, я думаю.
Тім Сегін,

7
@MatteoMosca ОП попросив "не передбачати покарання за продуктивність за доступ до стандартних масивів". Це стосується List <T>, незалежно від того, що таке T, тому всі ваші коментарі на цій сторінці є неточними.
Jim Balter

16

Перш за все, тримайтеся подалі від Arraylistабо Hashtable. Ці класи слід вважати застарілими, на користь дженериків. Вони все ще перекладаються цією мовою для застарілих цілей.

Тепер те, що ви шукаєте, це List<T>клас. Зверніть увагу, що якщо T є типом значення, у вас буде пам'ять contiguos, але не якщо T є еталонним типом, зі зрозумілих причин.


15

C # має багато посилальних типів. Навіть якщо контейнер зберігає посилання суміжно, самі об'єкти можуть бути розкидані по купі


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.